標籤:

Content Security Policy (CSP) 是什麼?為什麼它能抵禦 XSS 攻擊?


謝邀


什麼是CSP?

CSP是由單詞 Content Security Policy 的首單片語成,CSP旨在減少(注意這裡是減少而不是消滅)跨站腳本攻擊。

CSP是一種由開發者定義的安全性政策性申明,通過CSP所約束的的規責指定可信的內容來源(這裡的內容可以指腳本、圖片、iframe、fton、style等等可能的遠程的資源)。通過CSP協定,讓WEB處於一個安全的運行環境中。


示例:

1.只允許本站資源

Content-Security-Policy: default-src 『self』

2.允許本站的資源以及任意位置的圖片以及http://trustedscripts.example.com下的腳本。

Content-Security-Policy: default-src 『self』; img-src *;

script-src http://trustedscripts.example.com


更多關於CSP的介紹可以參考W3C的相關文檔: https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#content-security-policy-header-field

一部分中文翻譯:CSP - HTML5 Chinese Interest Group Wiki


CSP的討論

CSP的出現可以一定程度上的減少XSS的攻擊,但不一定意味著XSS的消失。


挺久之前過了一遍CSP的安全策略,很多人把它喻為XSS攻擊的終結者,因為這種策略不再像傳統只靠各種正則和特徵匹配來識別跨站攻擊Payload,而是直接從協議層把一些存在安全隱患的用法默認給幹掉了,把同源同域更發揮到了極致。把之前整理的內容發到這裡吧。

  1. CSP策略在默認的情況下是不允許使用data URIs資源的,如果要使用,那麼需要顯示的指定,比如:img-src "self" data:
  2. script-src:在處理腳本資源的時候設置"unsafe-inline"可以阻止內聯Js代碼的執行。使用unsafe-eval開關可以禁止eval,setTimeout,setInterval函數的執行。
  3. object-src:控制embed,code,archive applet等對象。
  4. style-src:會控制樣式表@import和rel時所引入的URI資源,設置unsafe-inline規則可以是瀏覽器拒絕解析內部樣式和內聯樣式定義。並不會阻止鏈入外部樣式表。
  5. img-src:可以控制圖片資源的連接,包括img標籤的src屬性,以及CSS3中的url()和image()方法,以及link標籤中的href屬性(當rel設置成與圖像相關的值,比如HTML支持的icon)
  6. media-src:控制媒體類型的外部鏈入資源,如video, audio, source, 和track標籤的src屬性。
  7. frame-src:控制內嵌框架包含的外部頁面連接:iframe or a frame。
  8. font-src:控制CSS中的@font-face
  9. connect-src:控制XMLHttpRequest中的open(),WebSocket,EventSource
  10. inline script和eval類型函數(包括eval、setInterval、setTimeout和new Function())是不被執行的。另外data URIs也是默認不允許使用的,XBL,只允許通過chrome:和resource:形式uri請求的XBL,其它的比如在CSS中通過-moz-binding來指定的XBL則不允許被執行。

關於Bypass:

  1. 通過CRLF相應頭分裂注入來BypassCSP需要將新的相應頭插入到原來的CSP下面,在處理相同名字的Http頭時候,少數瀏覽器是根據第一次出現的來設置,大部分則是根據最後一次出現的同名Http頭來設置。這種屬於偽繞過。
  2. 請參考kuza55大神的Bypassing Content-Security-Policy,講了很多通過第三方前端框架的特性實現繞過的case,基本覆蓋全了。

綜述:
個人愚見,首先CSP是可以在一定程度上提高XSS的攻擊難度的,甚至杜絕XSS,前提是CSP策略用的好。還要考慮CSP能否普及,因為CSP在提供安全性的同時也提高了前端邏輯的複雜度,很多資源需要調整,類似QQ,新浪,搜狐這樣的站群,想通過合適的CSP同時提高安全性和易用性是很難的。


跨域腳本攻擊 XSS 是最常見、危害最大的網頁安全漏洞。

為了防止它們,要採取很多編程措施,非常麻煩。很多人提出,能不能根本上解決問題,瀏覽器自動禁止外部注入惡意腳本?這就是"網頁安全政策"(Content Security Policy,縮寫 CSP)的來歷。本文詳細介紹如何使用 CSP 防止 XSS 攻擊。

一、簡介
CSP 的實質就是白名單制度,開發者明確告訴客戶端,哪些外部資源可以載入和執行,等同於提供白名單。它的實現和執行全部由瀏覽器完成,開發者只需提供配置。CSP 大大增強了網頁的安全性。攻擊者即使發現了漏洞,也沒法注入腳本,除非還控制了一台列入了白名單的可信主機。

兩種方法可以啟用 CSP。一種是通過 HTTP 頭信息的Content-Security-Policy的欄位。

Content-Security-Policy: script-src "self"; object-src "none";
style-src cdn.example.org third-party.org; child-src https:

另一種是通過網頁的&標籤。

&

上面代碼中,CSP 做了如下配置。

  • 腳本:只信任當前域名
  • &標籤:不信任任何URL,即不載入任何資源
  • 樣式表:只信任http://cdn.example.org和http://third-party.org
  • 框架(frame):必須使用HTTPS協議載入
  • 其他資源:沒有限制

啟用後,不符合 CSP 的外部資源就會被阻止載入。
Chrome 的報錯信息。

Firefox 的報錯信息。

二、限制選項
CSP 提供了很多限制選項,涉及安全的各個方面。

2.1 資源載入限制
以下選項限制各類資源的載入。

  • 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 文件

2.2 default-src
default-src用來設置上面各個選項的默認值。

Content-Security-Policy: default-src "self"

上面代碼限制所有的外部資源,都只能從當前域名載入。如果同時設置某個單項限制(比如font-src)和default-src,前者會覆蓋後者,即字體文件會採用font-src的值,其他資源依然採用default-src的值。

2.3 URL 限制
有時,網頁會跟其他 URL 發生聯繫,這時也可以加以限制。

  • frame-ancestors:限制嵌入框架的網頁
  • base-uri:限制&
  • form-action:限制&

2.4 其他限制
其他一些安全相關的功能,也放在了 CSP 裡面。

  • block-all-mixed-content:HTTPS 網頁不得載入 HTTP 資源(瀏覽器已經默認開啟)
  • upgrade-insecure-requests:自動將網頁上所有載入外部資源的 HTTP 鏈接換成 HTTPS 協議
  • plugin-types:限制可以使用的插件格式
  • sandbox:瀏覽器行為的限制,比如不能有彈出窗口等。

2.5 report-uri
有時,我們不僅希望防止 XSS,還希望記錄此類行為。report-uri就用來告訴瀏覽器,應該把注入行為報告給哪個網址。

Content-Security-Policy: default-src "self"; ...; report-uri /my_amazing_csp_report_parser;

上面代碼指定,將注入行為報告給/my_amazing_csp_report_parser這個 URL。
瀏覽器會使用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":允許執行頁面內嵌的標籤和事件監聽函數
  • unsafe-eval:允許將字元串當作代碼執行,比如使用eval、setTimeout、setInterval和Function等函數。
  • nonce值:每次HTTP回應給出一個授權token,頁面內嵌腳本必須有這個token,才會執行
  • hash值:列出允許執行的腳本代碼的Hash值,頁面內嵌腳本的哈希值只有吻合的情況下,才能執行。

nonce值的例子如下,伺服器發送網頁的時候,告訴瀏覽器一個隨機生成的token。

Content-Security-Policy: script-src "nonce-EDNnf03nceIOfn39fn3e9h3sdfa"

頁面內嵌腳本,必須有這個token才能執行。

&

  • 被設計為一個完整的框架來防禦 XSS 和 CSRF 攻擊
  • 通常也可以用來控制 app 和擴展的許可權

CSP 允許開發者覆寫(SOP)每個 document 的許可權

  • Server 在 header 中定義規則

CSP 讓開發者提高了對 XSS 攻擊的防禦能力, 但也存在一些問題.

  • 難部署(如要改動左右inline scripts)
  • 對 Origin 的定義不夠細緻
  • Binary 安全

DEMO

資料庫里存了一個用戶輸入的信息, 簡單的彈窗JS.(外鏈JS也是同理)

&alert("I was stored by an attacker.");&

無CSP保護

有CSP保護


好像沒人提到nonce。。佔個坑回來答

內容安全策略 (CSP) 上面已經有很多人講了,CSP本身也可以比較好的解決XSS的問題,但事實上,XSS的重災區常常在Inline JavaScript,CSP1.1不能解決這個問題。


CSP2開始支持nonce-來解決Inline JavaScript的問題,在HTTP Header中聲明一個隨機字元串,在HTML中的JavaScript標籤上帶了nonce屬性,nonce的值和Header指定的一致才會執行對應的JavaScript代碼。

講的比較抽象,舉個例子吧:


&
&
&Hello CSP2&

&