內容安全策略(CSP)詳解
內容安全策略(CSP),其核心思想十分簡單:網站通過傳送一個 CSP 頭部,來告訴瀏覽器什麼是被授權執行的與什麼是需要被禁止的。其被譽為專門為解決XSS攻擊而生的神器。
1.CSP是什麼
CSP指的是內容安全策略,為了緩解很大一部分潛在的跨站指令碼問題,瀏覽器的擴充套件程式系統引入了內容安全策略(CSP)的一般概念。這將引入一些相當嚴格的策略,會使擴充套件程式在預設情況下更加安全,開發者可以建立並強制應用一些規則,管理網站允許載入的內容。簡單來說,就是我們能夠規定,我們的網站只接受我們指定的請求資源。
2. CSP的意義
防XSS等攻擊的利器。CSP 的實質就是白名單制度,開發者明確告訴客戶端,哪些外部資源可以載入和執行,等同於提供白名單。它的實現和執行全部由瀏覽器完成,開發者只需提供配置。CSP 大大增強了網頁的安全性。攻擊者即使發現了漏洞,也沒法注入指令碼,除非還控制了一臺列入了白名單的可信主機。
3.CSP的分類
(1)Content-Security-Policy
配置好並啟用後,不符合 CSP 的外部資源就會被阻止載入。
(2)Content-Security-Policy-Report-Only
表示不執行限制選項,只是記錄違反限制的行為。它必須與report-uri
選項配合使用。
4.CSP的使用
(1)在HTTP Header上使用(首選)
"Content-Security-Policy:" 策略
"Content-Security-Policy-Report-Only:" 策略
(2)在HTML上使用
<meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only" content="策略">
Meta 標籤與 HTTP 頭只是行式不同而作用是一致的,如果 HTTP 頭與 Meta 定義同時存在,則優先採用 HTTP 中的定義。
如果使用者瀏覽器已經為當前文件執行了一個 CSP 的策略,則會跳過 Meta 的定義。如果 META 標籤缺少 content 屬性也同樣會跳過。
5.策略應該怎麼寫
(1)舉個例子
// 限制所有的外部資源,都只能從當前域名載入
Content-Security-Policy : default-src 'self'
// default-src 是 CSP 指令,多個指令之間用英文分號分割;多個指令值用英文空格分割
Content-Security-Policy: default-src https://host1.com https://host2.com; frame-src 'none'; object-src 'none'
// 錯誤寫法,第二個指令將會被忽略
Content-Security-Policy: script-src https://host1.com; script-src https://host2.com
// 正確寫法如下
Content-Security-Policy: script-src https://host1.com https://host2.com
// 通過report-uri指令指示瀏覽器傳送JSON格式的攔截報告到某個地址
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
// 報告看起來會像下面這樣
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
(2)常用的CSP指令
指令 | 指令和指令值示例 | 指令說明 |
---|---|---|
default-src | ‘self’ cdn.guangzhul.com | 預設載入策略 |
script-src | ‘self’ js.guangzhul.com | 對 JavaScript 的載入策略。 |
style-src | ‘self’ css.guangzhul.com | 對樣式的載入策略。 |
img-src | ‘self’ img.guangzhul.com | 對圖片的載入策略。 |
connect-src | ‘self’ | 對 Ajax、WebSocket 等請求的載入策略。不允許的情況下,瀏覽器會模擬一個狀態為 400 的響應。 |
font-src | font.cdn.guangzhul.com | 針對 WebFont 的載入策略。 |
object-src | ‘self’ | 針對 、 或 等標籤引入的 flash 等外掛的載入策略。 |
media-src | media.cdn.guangzhul.com | 針對媒體引入的 HTML 多媒體的載入策略。 |
frame-src | ‘self’ | 針對 frame 的載入策略。 |
report-uri | /report-uri | 告訴瀏覽器如果請求的資源不被策略允許時,往哪個地址提交日誌資訊。 特別的:如果想讓瀏覽器只彙報日誌,不阻止任何內容,可以改用 Content-Security-Policy-Report-Only 頭。 |
(3)其他的CSP指令
指令 | 指令和指令值示例 | 指令說明 |
---|---|---|
sandbox | 設定沙盒環境 | |
child-src | 主要防禦 <frame> ,<iframe> |
|
form-action | 主要防禦 <form> |
|
frame-ancestors | 主要防禦 <frame> ,<iframe> ,<object> ,<embed> ,<applet> |
|
plugin-types | 主要防禦 <object> ,<embed> ,<applet> |
(4)CSP指令值
指令值 | 指令和指令值示例 | 指令值說明 |
---|---|---|
* | img-src * | 允許任何內容。 |
‘none’ | img-src ‘none’ | 不允許任何內容。 |
‘self’ | img-src ‘self’ | 允許來自相同來源的內容(相同的協議、域名和埠)。 |
data: | img-src data: | 允許 data: 協議(如 base64 編碼的圖片)。 |
www.guangzhul.com | img-src img.guangzhul.com | 允許載入指定域名的資源。 |
*.guangzhul.com | img-src *.guangzhul.com | 允許載入 guangzhul.com 任何子域的資源。 |
‘unsafe-inline’ | script-src ‘unsafe-inline’ | 允許載入 inline 資源(例如常見的 style 屬性,onclick,inline js 和 inline css 等等)。 |
‘unsafe-eval’ | script-src ‘unsafe-eval’ | 允許載入動態 js 程式碼,例如 eval()。 |
6.支援問題
(1)CSP1相容性
瀏覽器可以很好地支援 CSP 1,全球高達94.66%,中國達到79.55%(截至2018年4月12日)。
(2)CSP2相容性
CSP 2還很新,支援相對少點,全球達81.11%,中國達到60.04%(截至2018年4月12日)。