cors-misconfiguration

star 72

CORS 配置错误检测 — 检测跨域资源共享配置错误;适用于 Web API、前后端分离、网关代理场景。

Q16G By Q16G schedule Updated 6/7/2026

name: cors-misconfiguration description: CORS 配置错误检测 — 检测跨域资源共享配置错误;适用于 Web API、前后端分离、网关代理场景。 when-to-use: 当任务涉及跨域访问控制、Origin 白名单、凭证跨域读取风险评估时 allowed-tools: bash,read_file,list_files,rg user-invocable: false

CORS 检测:跨域配置错误

成因引用

CORS 成因:source(攻击者控制的 Origin 头)→ sink(CORS 响应头:Access-Control-Allow-Origin / Access-Control-Allow-Credentials 等)。反射任意 Origin + Allow-Credentials=true,导致跨域读取受保护数据。详见同根目录 pentest/web-security-testing/SKILL.md 漏洞成因图谱 · CORS 配置错误行(不在本 skill 重复成因)。

关键 sink 形态:服务端在响应头里反射请求 Origin 作为 Access-Control-Allow-Origin 而不是用白名单——这是 CORS 配置错误的核心 sink,无论中间件实现方式如何(Go 反射 r.Header.Get("Origin") / Node CORS 通配 / Nginx 反向代理回填等)都属同 sink。

触发线索(基线检查项)

以下是已知的常见 CORS 触发线索,作为基线起点而非必检硬清单:

  • 适用且已完成 → 标注 [x] done
  • 明确不适用 → 标注 [-] n/a (原因)
  • 基线未列出但实际发现 → 新增条目并标注 [+] added (来源)

基线触发线索按"sink 语义"分类(不按业务命名):

  • 响应头含 Access-Control-Allow-Origin:任何返回 ACAO 头的端点都是候选——不限于"看起来像跨域"的 API
  • 反射 Origin 形态:响应的 Access-Control-Allow-Origin: <reflected from request Origin>(非固定白名单值)
  • Access-Control-Allow-Credentials: true:与上面任一组合都是高危——攻击者可携带凭证跨域读
  • null Origin 信任:服务端把 Origin: null 也作为合法值反射
  • 宽泛后缀 / 前缀匹配:如 evil.target.com 被信任(target.com 后缀匹配缺陷)
  • 预检过宽OPTIONS 预检返回 Access-Control-Allow-Methods/Headers 包含敏感方法 / 自定义头
  • 跨子系统覆盖:多个子系统都有独立 CORS 中间件——每个子系统的 CORS 配置都需独立测
  • 代码模式:后端代码出现 w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) + w.Header().Set("Access-Control-Allow-Credentials", "true") 形态

思考检查点

加载本 skill 时按这些问题思考:

  • 这个端点返回的 ACAO 是固定白名单还是反射 Origin?
  • 是否同时设置了 Allow-Credentials: true?(两者组合即高危)
  • 如果反射 Origin,是否也信任 null
  • 子系统级 vs 端点级 CORS:多子系统场景下,每个子系统的 CORS 中间件是不是都需独立测?
  • 端点返回的响应是否含敏感数据?(CORS 配置错误本身需结合"可读敏感数据"才判 confirmed)

方法论

  1. 基线请求(必做):不带 Origin 与带合法 Origin 各发起一次,记录 ACAO/ACAC/Vary
  2. 恶意 Origin 变异:使用 https://evil.examplenull、相似子域、随机端口等 Origin 重放请求
  3. 凭证场景验证:对需要登录的接口携带 Cookie/Authorization,观察是否允许跨域读敏感响应
  4. 预检验证(按需):发送 OPTIONS 预检,检查 Access-Control-Allow-Methods/Headers 是否过宽
  5. 复核:采用足以排除缓存、网关改写与偶发头部波动的方式,确认跨域读取行为真实存在

探测 payload 集

Origin payload 用途
https://evil.example 标准恶意 Origin
null 检测 null Origin 信任(如 sandboxed iframe)
https://evil.example:9999 端口变体,检查白名单是否含端口
https://target.com.evil.example 后缀匹配绕过
https://evil-target.com 前缀匹配绕过
http://evil.example(HTTP 而非 HTTPS) 协议混合

示例库

正例形态(代码层根因)

  • w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) + w.Header().Set("Access-Control-Allow-Credentials", "true") — Go 中间件直接反射 Origin(origin-reflected-with-credentials-cors
  • cors({ origin: true, credentials: true }) — Express CORS 配置 origin: true 反射所有 Origin(expressjs-origin-true-cors
  • w.Header().Set("Access-Control-Allow-Origin", "*") 但端点返回敏感数据 — 通配符 + 敏感数据(wildcard-acao-sensitive-cors

窄化反例(必须避免)

以下是 CORS 维度的典型窄化误判:

  • "已在某子系统命中 CORS 反射 → 其他子系统也假定有同问题" — 错误的另一面。CORS 是按子系统 / 按服务独立配置的,每个子系统的 CORS 中间件可能完全不同。必须对每个子系统独立测,但不能仅凭一个命中就推断其他全有(也不能反之,仅凭一个安全就推断其他全安全)
  • "已测了 GET 请求 → 跳过 OPTIONS 预检" — 错。预检可能暴露 Access-Control-Allow-Methods/Headers 配置过宽问题,必须独立测
  • "Access-Control-Allow-Origin: * 不算高危" — 不完全错,但当响应含敏感数据 + 需要凭证时仍属高危。需结合端点的数据敏感度判定
  • "参数名 / 路径不含 'api' → 跳过 CORS" — 错。任何返回 ACAO 头的端点都是候选,不限于显式 API 路径
  • "已测 https://evil.example → 跳过 null Origin" — 错。null Origin(来自 sandboxed iframe / file:// 等场景)是独立攻击面,需独立测

反例义务(必须遵守)

为什么这里是「必须」:反例义务属于交付契约——"该子系统 CORS 配置安全"或"已防护"结论是覆盖完整性的产物声明,缺失反向验证清单会让下游误信"该维度全站安全"。

写"未发现 CORS 配置错误"或"已防护"前,产物必须包含:

  • 测过的 CORS 候选端点完整清单(按 sink 语义枚举:所有返回 ACAO 头的端点;多子系统场景按子系统独立分组结账)
  • 每个端点测过的 Origin payload 类型(恶意 Origin / null / 子域 / 端口变体 / 协议变体)
  • 每个端点的响应证据(ACAO / ACAC / Vary 头是否反射 / 通配 / 白名单)
  • 凭证场景测试结果(带 Cookie/Authorization 是否仍允许跨域读)

清单不完整 → 结论降级为 partial-coverage 并显式声明未覆盖范围。

特别警示:多子系统场景下,CORS 配置按子系统独立结账——不能用"在子系统 A 测了"代替"子系统 B/C/D 也安全"的结论。

闭环验证要求(必须遵守)

通用闭环口径见同根目录 common/closure-verification.md(技能表 path 列同一抽取根下,需要时 read_file 读取)。核心:结论须形成「输入 → 处理 → 真实危害 → 可复核证据」完整证据链;仅凭响应头出现 Access-Control-Allow-Origin 等中间信号最多判 suspected,证明攻击源可携带凭证跨域读到敏感响应才判 confirmed

实际效果验证方向(至少证明一类)

  • 恶意 Origin 在真实浏览器跨域场景下能读取受保护接口返回的敏感数据
  • 凭证场景下,浏览器会携带 Cookie/Authorization,且响应对恶意站点可读
  • 若只有 ACAO/ACAC 头部异常,但未证明浏览器端真实可读性或敏感数据暴露,不能给 confirmed

判定标准

现象 判定
恶意 Origin 被允许,且在真实浏览器跨域场景下可读取敏感响应(含凭证场景) confirmed
配置看似宽松(如反射 / null),但尚未证明真实浏览器可读性或敏感数据暴露 suspected
仅允许受控白名单 Origin,且敏感接口无跨域读风险 not vulnerable
只测了部分子系统 / 端点 / Origin payload 类型 partial-coverage(不得宣称 safe)

关键检测要点

  • 必须结合"是否可读取敏感数据"判定风险,不能只看头字段存在
  • ACAO: * 常见于公开静态资源;若无敏感数据与凭证,不应直接判高危
  • 注意 Vary: Origin、缓存层与网关改写,避免一次性结果误判

修复建议

  • 使用严格 Origin 白名单(精确匹配协议+域名+端口)
  • 禁止在敏感接口对任意 Origin 返回可读权限
  • 仅在确有需要时启用 Access-Control-Allow-Credentials: true
  • Go 场景:避免 w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) 直接反射;改为白名单校验后输出
Install via CLI
npx skills add https://github.com/Q16G/aster --skill cors-misconfiguration
Repository Details
star Stars 72
call_split Forks 6
navigation Branch main
article Path SKILL.md
More from Creator