最近Google又推出了兩款有關CSP利用的小工具,其一爲CSP Evaluator,這是一個可以評估你當前輸入的CSP可否幫助你有效避免XSS攻擊的工具,其用法很是簡單,在輸入框中輸入你當前設置或將要設置的CSP值,選擇須要驗證的CSP版本,而後按下「CHECK CSP」便可。不知道CSP是什麼的同窗,能夠看下阿里聚安全博客之前推送的一篇文章《Content Security Policy 入門教程》javascript
下面的列表中會給出評估工具對你輸入CSP的安全性評估,全部條目用不一樣顏色標記了可能的影響程度。而且每一個條目均可以單擊展開詳情,以按照建議修復可能存在的缺陷。如圖:html
CSP Evaluator還存在一個Chrome插件版本,一樣易於使用。在使用了CSP的網站上單擊擴展圖標就能夠自動對當前頁面的CSP進行評估。java
另外一款工具爲CSP Mitigator,這款Chrome插件容許您將自定義CSP策略應用於應用程序。 它能夠幫助您瞭解啓用CSP的後果,識別與您的策略不兼容的應用程序部分,並指導您在部署前進行任何須要的更改。效果圖在Chrome商店中有,這裏就再也不贅述了。web
能夠看到,Google仍然在竭盡全力地推行CSP的發展與應用。在CSP Evaluator的頁面中,咱們看到Google相關團隊進行了一項規模巨大的研究來對CSP的現狀進行了深刻的分析,並基於這些結果,剖析了CSP的優缺點,並對CSP將來的發展給出告終論。就讓咱們跟隨這篇文章,來看看CSP在今世的表現與CSP的將來是否能夠期待。chrome
爲了研究CSP(Content Security Policy)對XSS攻擊的防禦做用,他們作了對CSP安全模型的首次深刻分析,分析了CSP標準中對web缺陷的保護能力,幫助識別常見的CSP策略配置的可能錯誤,而且展現了三類能使CSP無效化的繞過方法。編程
此次研究所採用的材料基於從Google搜索的索引文件中所提取到的CSP策略,從語料庫中提取了大約1060億頁的頁面,其中39億是受CSP保護的,其中確認了26,011個獨立的策略。他們發現,因爲策略配置錯誤和白名單條目不安全,這些策略中至少有94.72%沒法緩解XSS攻擊。基於這樣的研究結果,他們建議在實踐中部署CSP時,使用基於nonce的方法而不是傳統的白名單。而且,他們提出了名爲「strict dynamic」的新特性,這是當前在Chromium瀏覽器中實現的CSP3規範的一個新特性。如下會詳細講述爲什麼要使用這種策略和特性。瀏覽器
首先,何爲CSP?咱們知道,內容安全策略(CSP)是一種聲明機制,容許Web開發者在其應用程序上指定多個安全限制,由支持的用戶代理(瀏覽器)來負責強制執行。CSP旨在「做爲開發人員可使用的工具,以各類方式保護其應用程序,減輕內容注入漏洞的風險和減小它們的應用程序執行的特權」。當前,CSP還處在快速的發展期,目前正在進行規範中的版本是CSP3,CSP標準由用戶代理選擇實現。例如,Chromium具備完整的CSP2支持,而且實現了CSP3的大部分工做草案,僅在某些狀況下可能會落後於實驗中的某些特性,而Mozilla Firefox和基於WebKit的瀏覽器則剛剛得到了完整的CSP2支持。在實際使用中,CSP策略在Content-Security-Policy HTTP響應頭或 元素中提供。安全
1.資源加載限制。 CSP的最廣爲人知和經常使用的方面是將各類子資源的加載限制到開發人員容許的一組源的能力,這組源稱爲源列表。 經常使用的指令是script-src,style-src,img-src和兜底的 default-src; 調節資源的指令的完整列表以下表1所示。做爲特殊狀況,script-src和style-src指令還有幾個額外的配置選項可用; 這些選項容許對腳本和樣式表進行更細粒度的控制。markdown
2.基於URL的限制。 某些類型的攻擊不能經過管理子資源來防止,但與之相似,對於文檔也須要有能夠與之交互的可信來源的概念。 一個常見的例子是frame ancestors指令,它定義了容許的框架來源,以防止點擊劫持。 相似地,base-uri和form-action定義哪些URL能夠是<base#href>和<form#action>元素的目標,以防止一些Post XSS攻擊。app
3.雜項限制和強化選項。因爲在Web應用程序中缺少可以啓用安全限制的其餘常見機制,CSP已經成爲幾個鬆散適用的安全功能的集合。 這些功能包括block-all-mixed-content和upgrade-insecurerequests,它們能夠防止HTTPS混合內容錯誤並幫助改進HTTPS支持; plugin-types可以限制容許的插件格式; 還有sandbox,它反映了HTML5沙箱框架的安全功能。
經過這些能力咱們能夠看出,目前的CSP提供了對三種類型漏洞的保護功能:
XSS:XSS攻擊能在一個脆弱的應用程序中注入並執行不受信任的腳本(用script-src和object-src指令來進行保護)
Clickjacking:Clickjacking經過在攻擊者控制的頁面上覆蓋隱藏的框架來迫使用戶在受影響的應用程序中執行不想要的操做。(經過限制框架嵌入和 frame-ancestors指令來保護)
Mixed content:Mixed content意味着在經過用HTTPS傳遞的頁面上使用不安全協議加載資源(使用upgrade-insecure-requests和blockall-mixed-content關鍵字進行保護,限制將腳本和敏感資源加載到https網頁中)
在談論CSP帶來的好處以前,咱們須要注意到。因爲一些比較受歡迎的用戶代理(瀏覽器)還不支持或者僅對CSP提供部分支持,因此若是應用僅僅依賴CSP做爲深度防護的手段會很容易讓安全機制徹底失敗。所以,在使用CSP以外還必須採用傳統保護機制; 例如,在生成HTML代碼時使用帶有嚴格上下文轉義的框架,使用X-Frame-Options Header以防止點擊劫持,並確保資源在安全頁面上經過HTTPS協議獲取。請務必記住,設置CSP的實際好處是,當主要的安全機制不夠用時,CSP能夠在開發人員引入編程錯誤時保護用戶遠離可能致使的XSS,點擊劫持或者混合內容錯誤。
事實上,因爲點擊劫持能夠經過X-Frame-Options來避免,而混合內容錯誤在現代瀏覽器中已經默認被阻止了。所以CSP做爲標準被提出的最主要目的,就是用於防禦XSS攻擊。而XSS,也正是既能經過CSP來緩解,又是開發者常常容易引入應用的錯誤。在實現用CSP防止沒必要要的腳本執行時,咱們制定的策略必須知足三個要求:
1.策略必須同時定義script-src和object-src(或者使用default-src來補全),在缺乏任意一項時都可以被繞過:
2.script-src的源列表不能包含unsafe-inline關鍵詞(除非使用nonce)或者容許data: URI,不然能夠被繞過:
3.script-src和object-src源列表不能包含含有攻擊者可控制response的安全相關部分的源地址,或包含不安全的庫。不然能夠被繞過:
若是以上任意一條沒有被知足的話,整個CSP對於XSS的防禦就會完全失效。
因爲CSP的基本假設之一就是在策略白名單中的域名只會提供安全的內容,所以從理論上來講攻擊者不該該可以將有效的JavaScript注入到白名單裏來源的響應中。然而在實踐中,咱們發現現代web應用程序每每會由於幾種模式違反這個假設。
1.JavaScript帶有用戶可控的回調:某些JSONP函數接受用戶傳遞的函數名,但未作嚴格的過濾,致使能夠注入任意JavaScript代碼執行,即便作了基本的過濾,也可能使用SOME攻擊來注入任意函數名:
2.反射或者符號執行:CSP對於腳本執行的限制可能(一般是意外地)被白名單中的腳本所規避。 例如,腳本可使用反射來查找和調用全局做用域中的函數,如圖:
一般狀況下這些函數不會有太大危害,由於參數是開發人員所控制的。然而當函數從DOM獲取數據,而應用又有DOM注入的漏洞,則極可能被攻擊者徹底控制函數及其參數。一個典型的例子是目前流行的AngularJS庫,它具備強大的模板語法和客戶端模板執行:
默認狀況下AngularJS會經過eval來執行代碼,在特定的不容許eval的CSP場景下,AngularJS也支持使用「CSP compatibility mode」 (ng-csp)來執行模板的代碼。攻擊者只須要從白名單中的域名裏引入AngularJS,就能夠在頁面上經過注入ng-app標籤來編寫可以執行任意JavaScript代碼的模板。
3.意料以外的可被當作的JavaScript來解析的響應:經過瀏覽器對MIME的檢查寬鬆來執行任意js,好比僞造腳本響應類型。若是被黑客控制響應的話,在白名單中script-src和object-src均可能存在隱患。
4.做爲安全手段的路徑限制:CSP2中的whitelist能夠指定路徑(目錄),然而若是白名單中的條目包含30X重定向,且能被黑客控制,則能夠繞過CSP。
最多見於OAuth中,或被用於防止referer丟失。
爲了找出互聯網中有多少CSP策略可以切實有效地防禦XSS攻擊,Google團隊構造了一些數據集並進行了標準化處理。根據咱們以上的結論,想要達到好的XSS防禦效果,CSP的XSS保護策略必須處在強制模式下,而且至少包含如下兩個指令之一:script-src或default-src。所以能夠據此肯定含有XSS防禦的CSP策略。對於策略的安全性檢查,他們採用了以下幾種方式檢驗:
1.對於「unsafe-inline」的使用:對於一個使用了「unsafe-inline」而且沒有使用nonce的策略,能夠認爲是很容易被繞過的。
2.缺乏「object-src」:一個指定了「script-src」策略可是沒有指定「object-src」(同時也沒有「default-src」)的策略,是很容易用plugin繞過的。
3.在白名單中使用通配符:在白名單中使用通配符,或者使用URI Scheme很容易引發包含任意域名內容。
4.白名單中包含不安全的來源:若是白名單中的來源可能存在CSP Bypass,則也是不安全的。
對於如何檢查存在CSP bypass的域名,咱們定義爲:
1.託管了AngularJS的域名,由於AngularJS容許在模板中執行任意代碼。
2.暴露了JSONP接口的域名(可使用JSONP任意定義js代碼,或者SOME攻擊自定義函數名)。
在進行了一系列數據的處理和分析以後,他們獲得的結論是。在數據集中,有3,913,578,446(3.7%)個網址採用了CSP。 全部主機名中的1,664,019(0.16%)採用了CSP。他們將整個數據集分爲3類:
1.全部策略
2.XSS-Protection 策略(至少含有script-src,object-src或者default-src之一)
3.嚴格XSS-Protection 策略(在2的基礎上,不含unsafe-inline,unsafe-eval等,且URI Scheme,或者白名單通配符)
在此基礎上,獲得了目前互聯網上CSP安全的總覽:
1.全部策略數據中的94.72%並無提供XSS防禦
2.在全部提供XSS防禦的數據中,有94.68%能夠被繞過
3.在全部提供XSS防禦的數據中,有87.3%指定了unsafe-inline而且沒有部署nonce
4.在全部提供XSS防禦的數據中,有9.4%既沒有指定object-src,也沒有default-src
5.在全部提供XSS防禦的數據中,有21.48%使用了通配符或者URI Scheme
6.在忽略3,5的狀況下,仍有51.05%的能夠被繞過。有些是由於4,更多的是由於script-src中的白名單中包含了不安全的域
經過對於所獲得的對XSS有效的CSP防禦策略的分析,咱們獲得了白名單的安全性以下:
1.白名單數量越大,越難保證JSONP和AngularJS形成的安全問題
2.大概在嚴格策略中的41.65%,全部XSS防禦策略中的79.17%,包含不安全的白名單
3.在使用12條白名單時,繞過率達到了94.8%
4.做爲結果,咱們得出的結論是,部署傳統的基於白名單的CSP模型中防止XSS是不可行的,由於在實踐中腳本執行限制一般能夠被推翻。
能夠看出,script-src的白名單是形成CSP失效的最大緣由(除了沒配置好的unsafe-inline和缺乏object-src以外)。所以,咱們應該如何改進CSP呢。其實CSP已經提供了更精細的方法來對信任腳本:加密隨機數(cryptographic nonce)和哈希(hash)。 特別是nonces容許開發人員明確地註解每一個受信任的腳本(不論內聯和外部),同時禁止攻擊者注入的腳本執行。 爲了提升CSP的總體安全性,Google據此提出了一種稍微不一樣的策略寫法。 應用程序維護者應該應用基於nonce的保護方法,而不是依賴白名單。 如下列表描述了基於白名單的CSP策略和知足此策略的腳本:
能夠看出,白名單中包含了一個不安全的域名,所以所述CSP的策略就是不安全的。攻擊者能夠經過JSONP暴露出的點來注入惡意代碼: https://example.org/script?callback=malicious_code.
爲了防止這種事情的發生,咱們使用nonce來定義策略。在nonce中,應用程序定義並生成了單一的,不可猜想的令牌(nonce),這個令牌會同時傳遞給CSP策略和做爲一個合法HTML屬性傳遞給script。 用戶代理僅容許執行那些nonce值可以匹配策略中指定的值的腳本。雖然攻擊者能夠將標記注入易受攻擊的頁面,可是因爲不知道nonce的臨時值,所以他並不能執行惡意腳本。
經過使用nonce,能夠單獨將腳本列入白名單。 即便攻擊者可以定位XSS,nonce的值也是不可預測的,所以攻擊者不可能向JSONP注入有效腳本。並且因爲瀏覽器支持多個策略,所以能夠把nonce和whitelist一塊兒寫,用逗號隔開。nonce能夠用來將各個腳本列入白名單,而whitelist能夠用於集中實施安全策略。
那麼,當咱們生成動態腳本並插入時會發生什麼呢?由於新生成的,被插入到頁面的js並不知道nonce的值,因此會被攔截,所以須要CSP3裏的 script-src: ’strict-dynamic’。’ trict-dynamic’容許將信任關係傳遞給動態生成的腳本,也就是說,「strict-dynamic」容許js動態添加的腳本執行,而忽略script-src的白名單。而且,其餘的script-src白名單會被忽略,瀏覽器不會執行靜態或解析器插入的腳本,除非它伴隨有效的nonce值。這裏的關鍵點是,使用createElement()來插入js時,可以執行createElement()的js已經被信任了,而且黑客不知道nonce的時候沒法注入惡意腳本。所以咱們能夠信任新建的js代碼。舉例,咱們能夠這麼寫CSP: