Defaults.Exposed › 修復 › 內容安全策略(CSP)
如何修復 內容安全策略(CSP)
內容安全策略是你的網站交給每個訪客瀏覽器的一條安全規則,明確告訴它哪些程式碼獲准執行。沒有它,一旦有惡意東西落到頁面上——透過一個留言框、一個被黑的外掛、或一個第三方腳本——瀏覽器就會隨意執行它,包括在你客戶輸入時悄悄盜取卡號和密碼的程式碼,而那把鎖還顯示著。
對您業務的關鍵影響: 你的網站一旦被篡改,惡意程式碼就能在一切看起來完全正常的情況下,直接從你自己的結帳頁面讀走客戶的支付卡和登入資訊——留給你的是退款、欺詐索賠、一樁須上報的資料外洩,以及一個大客戶安全團隊用來擱置或扼殺生意的檢查失敗。
這會讓您付出什麼代價
- 隱藏的程式碼溜進你的某個頁面,悄悄複製你客戶在結帳時輸入的每一個卡號和密碼,發給攻擊者,而你的網站看起來完全正常——你只在欺詐投訴到來時才發現。
- 一個騙子在你真實的網站上植入一個假的「在此付款」表單,把款項收進他自己的帳戶;客戶以為付給了你,貨沒到時罵你,並索回他們的錢。
- 一個大客戶的安全團隊掃描你的網站,發現這項基本保護被關著,把它標記出來——讓你的合約擱置或丟失,直到你能證明已修好。
- 一樁追溯到缺失標準防護的外洩變成一起須上報的事故:監管方的質詢、客戶通知,以及一次遠比那個免費修復更昂貴的名譽打擊。
為什麼它重要。 那把鎖證明到你網站的連線是私密的,但它對訪客上了頁面之後哪些程式碼執行毫無控制。內容安全策略正是那個有控制的防護——它告訴瀏覽器忽略任何並非來自你信任來源的腳本,於是一個被篡改的欄位、廣告或外掛,無法被變成盜取你客戶金錢和資料的工具。它是你評分卡上的一項計分檢查,值實打實的分數,也是一次專業安全稽核最先查的東西之一。
這是什麼,大白話版
當有人訪問你的網站時,他的瀏覽器下載你的頁面並執行上面的任何程式碼——那些讓選單下拉、按鈕運作、支付表單提交等等的腳本。預設情況下,瀏覽器信任所有這些。它無從知道哪些程式碼真正是你的、哪些是別人偷偷塞進來的。
一個內容安全策略(常簡稱 CSP)是你的網站附加到每個頁面上的一份簡短規則清單,告訴瀏覽器:「只執行來自我批准的這些來源的程式碼,其餘一概拒絕。」 這是一家誰都放進去的夜店和一家門口有賓客名單的夜店之間的區別。
它之所以如此重要,是因為網站不斷被篡改——並不總是透過黑掉你的伺服器,而是透過多數網站留著的那些後門:一個留言欄位、一個搜尋框、一個過時的外掛、一個用於廣告或分析的第三方腳本,或一個聊天小工具。如果攻擊者哪怕把一行他自己的程式碼弄到你的某個頁面上,瀏覽器就會把它當作你的來執行。從那裡它能讀走你客戶輸入的一切——卡號、密碼、地址——並悄悄送往別處。內容安全策略透過拒絕執行任何來自你未批准來源的東西,關上那扇門。
這會讓你付出什麼代價
這不抽象。內容安全策略所防止的攻擊——注入頁面、從你自己客戶那裡盜取資料的程式碼——是有記錄以來一些最大的刷卡外洩的幕後元凶。下面是它對一家普通企業往往如何上演:
- 隱形的結帳盜刷器。 攻擊者透過一個有漏洞的外掛或一個被攻陷的第三方腳本,把幾行程式碼溜上你的結帳頁面。你客戶輸入的每一個卡號、姓名和 CVV 都被即時複製並發給攻擊者。你的網站看起來、用起來都完美;那把鎖也在。你幾週後才發現,當你的支付服務商打電話來說一簇欺詐回報全都追溯回你的店鋪。現在你面對的是退款、一次強制安全稽核、可能喪失收卡資格,以及一樁你可能依法須上報的外洩。
- 假的支付表單。 一個騙子往你真實的網站上注入一個以假亂真的「在此付款」框。客戶信任你的品牌而輸入他們的資訊;錢和資料都去了攻擊者那裡。客戶罵你——而他們沒罵錯,因為它發生在你的網站上。
- 丟掉的合約。 一個大客戶的安全團隊作為供應商盡職調查的一部分,對你的網站做一次自動掃描。一個缺失的內容安全策略立刻作為高嚴重度缺口冒出來。對一個採購或安全審查者而言,那一項缺失的防護讀起來就是「這個供應商連基本功都不做」——於是生意擱置,等他們要求整改,或悄悄花落於通過了檢查的競爭對手。
- 須上報的外洩。 當一樁資料外洩被追溯到一個缺失的、標準的、免費的防護時,它就不再是運氣不好,而開始看起來像疏失。這改變了監管方的質詢、客戶通知義務,以及代價——既包括罰款,也包括那個在事故結案後久久不散的名譽損害。
- 被攻陷的廣告或小工具。 許多網站從外部方載入程式碼——廣告網路、字型、支援聊天、分析。其中任何一個一旦被攻破,惡意程式碼就直接搭車進你的頁面。內容安全策略透過只允許你信任的特定外部來源,限制了爆炸半徑,於是一個供應商的外洩不會自動變成你的。
它到底是什麼(細節)
一個內容安全策略以一個 HTTP 回應標頭的形式傳遞——一行你的 Web 伺服器隨每個頁面發送的內容。它的值是一組指令,每條命名一類內容及其允許的來源。例如:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self'
用大白話說,這是:預設只從我自己的網站載入東西;只執行來自我自己網站的腳本;不允許任何老式外掛;並且不讓其他網站把我的網站嵌進一個框架裡。
「好」長什麼樣。 我們的檢查不只是看標頭是否存在——它像一個安全審查者那樣,逐條指令地讀這個策略,給它實際有多強評分。一個強壯的策略:
- 設一個限制性的基線(
default-src 'self'),只為你真正使用的特定可信第三方放寬它。 - 避開那些漏洞。 它不為腳本使用
'unsafe-inline'或'unsafe-eval',也不為腳本使用萬用字元(*)或光禿禿的協定來源(比如https:)——這些實際上重新打開了策略本該關上的那扇門。在確實需要內嵌腳本的地方,它使用一個 nonce 或 hash,讓只有你特定批准的程式碼才執行。 - 用
frame-ancestors 'self'鎖死框架嵌入(這也攔截了「嵌入你的網站來哄騙你客戶」的攻擊),並用object-src 'none'停用遺留外掛。 - 是強制執行的,而非僅回報。 一個
Content-Security-Policy-Report-Only標頭只觀察;它提供零執行時保護。我們的檢查只給它一小部分信用,絕不記為通過。你只有在策略強制執行後才受保護。
一個存在卻依賴 'unsafe-inline'、'unsafe-eval' 或萬用字元的策略仍會得分很低——因為實際上它提供的真實保護很少。目標是一個收緊的策略,而不只是隨便一個策略。
如何修復(免費,約 1–2 小時)
把這個交給你的 IT 人員或運營你網站的人——修復本身完全免費。 我們只對長期監控它是否保持就位、保持正確收費;打開它分文不取。它要花一兩個小時而非幾分鐘的原因,是那個防止它不小心攔掉你自己網站某些部分的小心試運行步驟。
-
以僅回報模式起步——暫不強制執行。 新增一個
Content-Security-Policy-Report-Only回應標頭。它觀察並記錄「會被」攔掉什麼,卻不真正攔截任何東西,於是即時網站照常運作,同時你了解每個頁面真正依賴什麼。(重要:僅回報本身不給訪客任何保護——它只是穩妥的第一步。) -
從你網站實際使用的東西出發構建策略。 審查回報,找出每一個合法的腳本、樣式、字型和圖片來源——你自己的網域、你的分析、你的支付服務商、你的字型託管、你的聊天小工具——把它們列為允許的來源。一個紮實的起點是
default-src 'self'加上你真正使用的可信第三方的明確條目。 -
避開那些擊穿整個意義的漏洞。 遠離腳本的
'unsafe-inline'和'unsafe-eval',並避免腳本的萬用字元來源如*和光禿禿的協定如https:——這些重新打開了策略本該關上的那個缺口。在內嵌腳本不可避免的地方,使用一個 nonce 或 hash,讓只有你特定批准的程式碼才執行。 -
鎖死框架嵌入和外掛。 加上
frame-ancestors 'self'(這也阻止其他網站嵌入你的來哄騙你客戶,並滿足相關的點擊劫持檢查)和object-src 'none'來攔截基於遺留外掛的攻擊。 -
從僅回報切換到強制執行。 一旦回報乾淨、網站運作,就把標頭名稱從
Content-Security-Policy-Report-Only改成Content-Security-Policy。這一步才真正交付保護——單有一個僅回報策略並不交付,也不會通過檢查。你在哪裡設這個標頭取決於你的平台:
- Cloudflare: Rules → Transform Rules → Modify Response Header → 設
Content-Security-Policy。(你也可以用 Cloudflare 做僅回報試運行。) - Nginx:
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self';" always; - Apache:
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'self';" - IIS(web.config): 新增一個名為
Content-Security-Policy的自訂 HTTP 回應標頭,以策略為其值。 - Google Workspace / Microsoft 365: 這些運行的是你的郵件,不是你的公開網站,所以策略設在你網站實際託管的地方(上面的 Cloudflare 或你的 Web 主機),而不是你的郵件管理後台。
- Cloudflare: Rules → Transform Rules → Modify Response Header → 設
-
重新檢測你的網域,確認策略現在顯示為已打開、且在強制執行,沒有削弱性的漏洞。
常見錯誤
- 止步於僅回報。 迄今最常見的錯誤:一個策略以僅回報模式加上,大家就翻篇了,而網站從未真正受保護。僅回報什麼都不攔。你必須切換到強制執行。
- 為了讓它「能用」而抓起
'unsafe-inline'。 當策略攔掉一個合法的內嵌腳本時,快速的辦法是允許所有內嵌腳本——但那重新打開了策略本該關上的那個洞。改用 nonce 或 hash。 - 使用萬用字元。
script-src裡一個光禿禿的*(或https:)允許來自任何地方的腳本,意味著策略幾乎不提供真實保護,仍會得分很低。 - 忘了第三方來源。 不先列出你使用的合法外部服務(分析、字型、支付小工具)就強制一個嚴格策略,會攔掉你自己網站的某些部分——這恰恰是僅回報試運行步驟存在的原因。
- 只在首頁上設它。 策略需要覆蓋每一個頁面,尤其是結帳、登入和帳戶頁面——那些才是值得攻擊的。
- 把它當作那把鎖的替代品。 內容安全策略和 HTTPS/HSTS 保護不同的東西。你全都要;一個不能替另一個擋著。
常見問題
我不懂技術——這個我自己能搞定嗎?
你不需要懂細節。這是由運營你網站或主機的人新增的一個設定,而在 Cloudflare 這樣的服務上它基本是有引導的。把下面的「如何修復」一節交給他們。它免費;唯一要當心的是,它應當先以僅觀察的試運行小心鋪開,以免不小心攔掉你自己網站的某些部分——而那恰恰是這些步驟所涵蓋的。
我已經有那把鎖和一張 SSL 憑證了——我的網站不就安全了嗎?
那把鎖保護你頁面的「傳輸」;它不管頁面「裡面」執行什麼。一旦惡意程式碼落到頁面上——透過一個被黑的外掛、一個被攻陷的廣告,或一個被注入的欄位——那把鎖不會阻止它盜取資料。內容安全策略是那個從一開始就限制允許執行什麼的層。它們保護不同的東西,你兩個都要。
打開這個會搞壞我的網站嗎?
如果一次性激進地打開就有可能,因為它可能攔掉你實際使用的合法腳本。這正是為什麼標準做法是先以「僅回報」試運行模式起步,它觀察而不攔截,修好它標記的任何東西,然後才強制執行。這樣做是安全的——而這個試運行步驟已內建在下面的修復裡。
我們已經把它放在「僅回報」模式了——這就被覆蓋了嗎?
沒有,而這是最常見的虛假安全感。僅回報模式觀察並記錄「會被」攔掉什麼,但它什麼都不攔——訪客得到的真實保護為零。它只是穩妥的第一步。我們的檢查只給僅回報一個真實策略的一小部分信用,並且不會把它記為通過。你只有切換到強制執行模式後才受保護。
這影響我們的評分,還是只是建議性的?
它影響你的評分。內容安全策略檢查是計分的,在網站安全類別中最高值 25 分。一個缺失或孱弱的策略被標為高嚴重度,會拉低你的評分——而它恰恰是一個客戶的安全問卷會問到的那類缺口。
我們的開發者加了一個策略,但分數還是很低——為什麼?
一個策略可以存在卻仍然孱弱。最常見的禍首是像腳本的「unsafe-inline」和「unsafe-eval」之類的漏洞,或萬用字元來源(一個光禿禿的 *),它們重新打開了策略本該關上的那個缺口。我們的檢查逐條指令地讀這個策略,並對那些弱點扣分——一個什麼都允許的策略,得分比沒有策略好不了多少。修復是用 nonce 或 hash 來收緊腳本規則,而不是那些漏洞。