内容安全策略(content-security-policy)
內容安全策略
- 1. iframe
- 點擊劫持與安全策略
- 服務端設置
- 解決思路
- 2. Content Security Policy,即內容安全策略
- 限制選項
- Content-Security-Policy-Report-Only
- 選項值
- script-src 的特殊值
- 注意點
1. iframe
在使用iframe 的時候
<iframe style="border:0;width:100%;height:100%" src="https://github.com/join"/>
經查 報的是
Refused to frame ‘https://github.com/’ because an ancestor violates the following Content Security Policy directive: “frame-ancestors ‘none’”.
原因是 點擊劫持與安全策略
點擊劫持與安全策略
禁止頁面被放在iframe里加載主要是為了防止點擊劫持(Clickjacking):
具體的,對于點擊劫持,主要有 3 項應對措施:
- CSP(Content Security Policy,即內容安全策略)
- X-Frame-Options
- framekiller
服務端設置
通過設置 HTTP 響應頭來聲明 CSP 和X-Frame-Options,例如:
# 不允許被嵌入,包括<frame>, <iframe>, <object>, <embed> 和 <applet> Content-Security-Policy: frame-ancestors 'none' # 只允許被同源的頁面嵌入 Content-Security-Policy: frame-ancestors 'self' # 只允許被白名單內的頁面嵌入 Content-Security-Policy: frame-ancestors www.example.com# 不允許被嵌入,包括<frame>, <iframe>, <embed> 和 <object> X-Frame-Options: deny # 只允許被同源的頁面嵌入 X-Frame-Options: sameorigin # (已廢棄)只允許被白名單內的頁面嵌入 X-Frame-Options: allow-from www.example.com還有個與frame-ancestors長得很像的frame-src,但二者作用相反,后者用來限制當前頁面中的與所能加載的內容來源
至于 framekiller,則是在客戶端執行一段 JavaScript,從而反客為主:
// 原版 <script> if(top != self) top.location.replace(location); </script>// 增強版 <style> html{display:none;} </style> <script> if(self == top) {document.documentElement.style.display = 'block'; } else {top.location = self.location; } </script>而 Github 登錄頁,同時設置了 CSP 和X-Frame-Options響應頭:
content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; connect-src 'self' uploads.github.com www.githubstatus.com collector.githubapp.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com cdn.optimizely.com logx.optimizely.com/v1/events wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; frame-src render.githubusercontent.com octocaptcha.com; img-src 'self' data: github.githubassets.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; worker-src github.com/socket-worker-5029ae85.js gist.github.com/socket-worker-5029ae85.js Content-Security-Policy: frame-ancestors 'none'; X-Frame-Options: deny因此無法通過iframe嵌入,那么,有辦法打破這些限制嗎?
解決思路
在資源響應到達終點之前的任意環節,攔截下來并改掉 CSP 與X-Frame-Options,比如在客戶端收到響應時攔截篡改,或由代理服務轉發篡改
而另一種思路很有意思,借助Chrome Headless加載源內容,轉換為截圖展示到iframe中。例如Browser Preview for VS Code:
2. Content Security Policy,即內容安全策略
為了防止它們,要采取很多編程措施,非常麻煩。很多人提出,能不能根本上解決問題,瀏覽器自動禁止外部注入惡意腳本?
這就是"網頁安全政策"(Content Security Policy,縮寫 CSP)的來歷
CSP 的實質就是白名單制度,開發者明確告訴客戶端,哪些外部資源可以加載和執行,等同于提供白名單。它的實現和執行全部由瀏覽器完成,開發者只需提供配置。
CSP 大大增強了網頁的安全性。攻擊者即使發現了漏洞,也沒法注入腳本,除非還控制了一臺列入了白名單的可信主機。
兩種方法可以啟用 CSP。
- 通過 HTTP 頭信息的Content-Security-Policy的字段。
- 通過網頁的標簽
,CSP 做了如下配置:
腳本:只信任當前域名
標簽:不信任任何URL,即不加載任何資源
樣式表:只信任cdn.example.org和third-party.org
框架(frame):必須使用HTTPS協議加載
其他資源:沒有限制
啟用后,不符合 CSP 的外部資源就會被阻止加載。
限制選項
- script-src:外部腳本
- style-src:樣式表
- img-src:圖像
- media-src:媒體文件(音頻和視頻)
- font-src:字體文件
- object-src:插件(比如 Flash)
- child-src:框架
- frame-ancestors:嵌入的外部資源(比如、、和)
- connect-src:HTTP 連接(通過 XHR、WebSockets、EventSource等)
- worker-src:worker腳本
- manifest-src:manifest 文件
用來設置上面各個選項的默認值。
Content-Security-Policy: default-src ‘self’
#限制所有的外部資源,都只能從當前域名加載。
如果同時設置某個單項限制(比如font-src)和default-src,前者會覆蓋后者,即字體文件會采用font-src的值,其他資源依然采用default-src的值。
3. URL 限制
網頁會跟其他 URL 發生聯系,這時也可以加以限制。
有時,我們不僅希望防止 XSS,還希望記錄此類行為。report-uri就用來告訴瀏覽器,應該把注入行為報告給哪個網址。
上面代碼指定,將注入行為報告給/my_amazing_csp_report_parser這個 URL。
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;選項值
每個限制選項可以設置以下幾種值,這些值就構成了白名單。
主機名:example.org,https://example.com:443 路徑名:example.org/resources/js/ 通配符:*.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-src https://host1.com https://host2.com如果不設置某個限制選項,就是默認允許任何值。
script-src 的特殊值
除了常規值,script-src還可以設置一些特殊值。注意,下面這些值都必須放在單引號里面。
'unsafe-inline':允許執行頁面內嵌的<script>標簽和事件監聽函數 unsafe-eval:允許將字符串當作代碼執行,比如使用eval、setTimeout、setInterval和Function等函數。 nonce值:每次HTTP回應給出一個授權token,頁面內嵌腳本必須有這個token,才會執行 hash值:列出允許執行的腳本代碼的Hash值,頁面內嵌腳本的哈希值只有吻合的情況下,才能執行。 nonce值的例子如下,服務器發送網頁的時候,告訴瀏覽器一個隨機生成的token。 Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'頁面內嵌腳本,必須有這個token才能執行。
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>// some code </script>hash值的例子如下,服務器給出一個允許執行的代碼的hash值。
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='下面的代碼就會允許執行,因為hash值相符。
注意,計算hash值的時候,
除了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 的回調函數。
上面的代碼中,雖然加載的腳本來自當前域名,但是通過改寫回調函數,攻擊者依然可以執行惡意代碼。
總結
以上是生活随笔為你收集整理的内容安全策略(content-security-policy)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Domain Adaptation论文合
- 下一篇: 亚马逊SP-API对接-网站授权