CSP 頭部驗證工具
貼上 Content-Security-Policy 頭部的值,一次性驗證所有指令和來源值。可檢測 unsafe-inline 等高風險設定、缺失的 default-src 兜底、指令名稱拼寫錯誤,並以視覺化方式展示每個指令允許的來源。
檢視 CSP 標頭的內容
Content-Security-Policy 是一條以分號分隔的長串,單憑肉眼順下來,危險之處最易被漏過。本工具會把您貼入的值拆成指令與來源,把危險的設定、缺失的宣告與拼寫之誤一一揪出,並把每條指令究竟准許了什麼攤開來看。
其中最棘手的,莫過於指令名的拼寫之誤。 瀏覽器對不認識的指令一概默默忽略,於是把 script-src 寫成 scipt-src,既不報錯,那一段政策也就這麼一直什麼都不做。 同樣容易被忽略的是 default-src 的缺失:少了它,凡您未逐一寫明的指令便不受任何限制,防線上就此裂開一道口子。而把 unsafe-inline 放進 script-src,幾乎等於把「阻斷內嵌指令碼」這一採用 CSP 的首要目的一筆勾銷。
使用方法
-
貼入 CSP 標頭的值
把形如
default-src 'self'; script-src ...的字串照原樣放進去。 - 先試一試範例 好例與壞例都已備好,動手之前便可看出判定的分別。
-
閱讀所提出的各點
unsafe-inline、缺失的default-src與拼寫之誤都會被點名。 - 查看每條指令准許的來源 准許從何處載入,一覽便知。
用好本工具的小技巧
- CSP 通常以 HTTP 響應頭的形式下發,但也可以通過
<meta http-equiv="Content-Security-Policy">標籤設定(不過 report-uri 等部分指令在 meta 標籤中不生效)。 - 在生產環境正式啟用 CSP 之前,建議先使用 Content-Security-Policy-Report-Only 頭部——它只收集違規報告,方便你在不影響現有功能的前提下評估實際影響。
- 萬用字元(*)和 'unsafe-inline' 雖然能讓開發更省事,但會削弱 CSP 大部分的 XSS 防護能力,上線前務必收緊這類寬鬆策略。
- 同一指令重複書寫兩次不會合並取值,只有第一次出現生效。如需追加或覆蓋來源,請把所有值寫在同一條指令中。
- 瀏覽器 DevTools 控制台會以紅色「Refused to load...」資訊顯示被攔截的資源,除錯過嚴的 CSP 時應首先檢視這裡。
這些情境會用到
初次引入 CSP
在政策還離生產環境甚遠時,便可確認它是否照您的本意行事。
盤點既有的政策
日積月累長起來的政策,往往還留著早已無人使用的網域的許可。
由僅報告轉為強制
在 Content-Security-Policy-Report-Only 下試過的值,可在正式強制之前先行檢視。
輔助程式碼審查
把改動後的政策貼上,確認它並未因此變弱。
CSP 的術語
- 指令
- 如
script-src或img-src之類的條目,它言明某一類資源可從何處載入。 - default-src
- 凡未逐一寫明的指令所回落到的預設值。略去它,凡您未寫明的類別便不受限制。
- 'self'
- 只准許來自同源載入的來源運算式。
- 'unsafe-inline'
- 准許直接寫在 HTML 裡的指令碼與樣式的來源運算式。它幾乎斷送了對 XSS 的防禦,宜改用 nonce 或 hash。另外,同一來源清單中含有 nonce 或 hash 時,支援 CSP Level 3 的瀏覽器會忽略 'unsafe-inline'(為相容舊瀏覽器而並列書寫是常見做法)。
- nonce
- 把一個一次性的亂數同時寫進指令碼標籤與政策,使二者相對應的辦法。這是安全地准許內嵌程式碼的途徑。
- frame-ancestors
- 言明何人可將您的網站嵌入框架的指令。它是 X-Frame-Options 的後繼者。
常見問題
閒話 ― CSP 為何誕生:僅靠轉義從來都無法徹底防住 XSS
Content Security Policy 的構想最早可追溯到 2004 年前後 Robert Hansen 提出的想法,隨後從 2008 年左右開始,Mozilla 工程師 Brandon Sterne 主導將其整理成正式規範,最終在 2012 年形成了 W3C 的第一份候選推薦標準(Level 1)。當時跨站指令碼攻擊(XSS)是網路安全領域最緊迫的問題之一,人們逐漸意識到,僅依賴「開發者認真轉義每一處輸出」這種做法並不足以構成穩固的防線。CSP 正是作為一種縱深防禦機制被設計出來,讓瀏覽器本身來強制限制指令碼的合法來源。
CSP Level 2 引入了基於 nonce 和 hash 的內聯指令碼許可機制,使網站無需依賴 'unsafe-inline' 也能允許特定的內聯程式碼執行。隨後 Level 3 又新增了 'strict-dynamic',可以自動信任由已受信指令碼動態載入的子指令碼,大幅降低了大型網站維護基於主機名白名單的成本。
Google 持續在其自身的大規模服務中推行基於 nonce 的嚴格 CSP,並據此釋出研究成果指出:基於主機名的白名單方式經常可以被繞過,而基於 nonce 或 hash 的策略在實踐中有效得多。這一結論目前已被廣泛引用為 CSP 的最佳實踐,也說明真正關鍵的設計決策不只是「禁止哪些取值」,而是「從一開始就該基於哪種許可策略來構建」。