跨域腳本攻擊 XSS 是最常見、危害最大的網頁安全漏洞。
上面代碼指定,將注入行為報告給/my_amazing_csp_report_parser這個 URL。
瀏覽器會使用POST方法,發送一個JSON對象,下面是一個例子。
除了Content-Security-Policy,還有一個Content-Security-Policy-Report-Only字段,表示不執行限制選項,只是記錄違反限制的行為。它必須與report-uri選項配合使用。
四、選項值
每個限制選項可以設置以下幾種值,這些值就構成了白名單。
如果同一個限制選項使用多次,只有第一次會生效。
除了常規值,script-src還可以設置一些特殊值。注意,下面這些值都必須放在單引號里面。
頁面內嵌腳本,必須有這個token才能執行。
hash值的例子如下,服務器給出一個允許執行的代碼的hash值。
下面的代碼就會允許執行,因為hash值相符。
注意,計算hash值的時候,<script>標簽不算在內。
(3)必須特別注意 JSONP 的回調函數。
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
瀏覽器會使用POST方法,發送一個JSON對象,下面是一個例子。
{ "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" } }
三、Content-Security-Policy-Report-Only
除了Content-Security-Policy,還有一個Content-Security-Policy-Report-Only字段,表示不執行限制選項,只是記錄違反限制的行為。它必須與report-uri選項配合使用。
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
四、選項值
每個限制選項可以設置以下幾種值,這些值就構成了白名單。
- 主機名:http://example.org,https://example.com:443
- 路徑名:http://example.org/resources/js/
- 通配符:*.http://example.org,*://*.example.com:*(表示任意協議、任意子域名、任意端口)
- 協議名:https:、data:
- 關鍵字'self':當前域名,需要加引號
- 關鍵字'none':禁止加載任何外部資源,需要加引號
Content-Security-Policy: script-src 'self' https://apis.google.com
# 錯誤的寫法 script-src https://host1.com; script-src https://host2.com
# 正確的寫法 script-srchttps://host1.com https://host2.com
如果不設置某個限制選項,就是默認允許任何值。
五、script-src 的特殊值除了常規值,script-src還可以設置一些特殊值。注意,下面這些值都必須放在單引號里面。
- 'unsafe-inline':允許執行頁面內嵌的<script>標簽和事件監聽函數
- unsafe-eval:允許將字符串當作代碼執行,比如使用eval、setTimeout、setInterval和Function等函數。
- nonce值:每次HTTP回應給出一個授權token,頁面內嵌腳本必須有這個token,才會執行
- hash值:列出允許執行的腳本代碼的Hash值,頁面內嵌腳本的哈希值只有吻合的情況下,才能執行。
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa> // some code </script>
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
下面的代碼就會允許執行,因為hash值相符。
<script>alert('Hello, world.');</script>
除了script-src選項,nonce值和hash值還可以用在style-src選項,控制頁面內嵌的樣式表。
六、注意點
(1)script-src和object-src是必設的,除非設置了default-src。
因為攻擊者只要能注入腳本,其他限制都可以規避。而object-src必設是因為 Flash 里面可以執行外部腳本。
(2)script-src不能使用unsafe-inline關鍵字(除非伴隨一個nonce值),也不能允許設置data:URL。
下面是兩個惡意攻擊的例子。<img src="x" onerror="evil()"> <script src="data:text/javascript,evil()"></script>
(3)必須特別注意 JSONP 的回調函數。
<script src="/path/jsonp?callback=alert(document.domain)//"> </script>
上面的代碼中,雖然加載的腳本來自當前域名,但是通過改寫回調函數,攻擊者依然可以執行惡意代碼。
七、參考鏈接
CSP Is Dead, Long Live CSP! , by Lukas Weichselbaum
An Introduction to Content Security Policy, by Mike West
文章內容來源自《Content Security Policy 入門教程》,作者:阮一峰@螞蟻金服
