CORSの「甘い設定」は、もはや単なる設定ミスではない:境界防御の崩壊と戦術的対策
世界中のコードベースを監査していると、今なお絶滅しない「CORSの不適切な設定」に遭遇する。開発者が「とりあえず動かしたい」という一心で設定した Access-Control-Allow-Origin: や、正規表現による安易なオリジン検証。これらは単なる設定ミスではなく、ブラウザという「ユーザーの端末上で動く第三者のコード」に対して、あなたのアプリケーションの門戸を全開にする行為に他ならない。
インジェクション攻撃が「入力の検証」というフロントラインで戦うのに対し、CORSの誤設定は「セッションと境界の無効化」という、より高レイヤの信頼モデルを破壊する。今日は、この問題をアーキテクトの視点から、泥臭い現実と防御の論理で解剖していく。
—
1. CORSの設計思想:なぜ「オリジン」は脆弱なのか
CORSは、本来「同一オリジンポリシー(SOP)」というブラウザの強力な制約を、現実的なWebアプリケーションの要件(API連携やマイクロサービス)のために緩和する仕組みだ。しかし、ここにはブラウザの仕様上の大きな罠がある。
ブラウザは、Access-Control-Allow-Credentials: true が付与されている場合、ワイルドカード( にエコーバックする「動的ホワイトリスト」を実装する。)を許可しない。しかし、多くの開発者はこれを回避するために、リクエストヘッダーの Origin を読み取り、それをそのまま Access-Control-Allow-Origin
// 【脆弱な実装例:最悪のケース】
// リクエストのOriginを検証なしで信頼し、レスポンスヘッダーに反射させる
const origin = req.headers.origin;
if (isAllowed(origin)) { // この検証ロジックが正規表現の不備で突破される
res.setHeader(‘Access-Control-Allow-Origin’, origin);
res.setHeader(‘Access-Control-Allow-Credentials’, ‘true’);
}
この「エコーバック」こそが、攻撃者にとっての黄金の鍵だ。もし正規表現が ^https://.\.example\.com$ のような甘い設計であれば、攻撃者は https://attacker.example.com.evil.com というドメインを取得するだけで、あなたのAPIから機密情報をスクレイピングできる。
—
2. パケット構造とブラウザの挙動:信頼の連鎖を断ち切る
攻撃者は、巧妙に細工されたパケットを送り込む。特に重要なのは、OPTIONS メソッドによる「プリフライトリクエスト」だ。
- プリフライトの盲点: 多くの開発者は、自身のサーバーが
OPTIONSリクエストに対して適切にAccess-Control-Allow-HeadersやAccess-Control-Allow-Methodsを返しているか確認していない。攻撃者は、本来許可されるべきではないContent-Type: application/json以外のカスタムヘッダーを注入し、WAFや防御層をすり抜けるペイロードを試みる。
防御のアーキテクチャ:ホワイトリストの静的化
動的なオリジン検証は、今日から捨てろ。可能な限り、サーバーサイドの構成で静的に定義すべきだ。
【推奨:Nginxレベルでの厳格なホワイトリスト】
動的な反射を行わず、マップを使用して許可されたオリジンのみを返す
map $http_origin $cors_origin {
default “”;
“https://api.trusted.com” “https://api.trusted.com”;
“https://dashboard.trusted.com” “https://dashboard.trusted.com”;
}
server {
if ($cors_origin = “”) {
return 403; # ホワイトリスト外は即座に遮断
}
add_header ‘Access-Control-Allow-Origin’ $cors_origin always;
add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;
}
—
3. 生成AIとプロンプトインジェクションへの波及
今、最も警戒すべきは「生成AIのAPI連携」だ。LLMを組み込んだWebアプリケーションにおいて、CORSの不備は「AIへの直接的なプロンプト注入」を可能にする。
攻撃者は、被害者のブラウザで動作するスクリプトを介して、あなたのAIバックエンドに対し、認証情報を付与した状態でクロスオリジンリクエストを飛ばす。もしAIが「セッション情報からユーザーの個人情報を取得する」ような機能を持っていれば、CORSの穴はそのまま「AIを介したデータ漏洩」に直結する。
ガードレイルとしてのアーキテクチャ設計
1. API Gatewayでの認証分離: CORSのチェックをアプリケーション層で行うのではなく、API Gateway(AWS API Gateway, Kong, Apigee等)のポリシー層で集中管理する。
2. トークンのバインディング: DPoP (Demonstrating Proof-of-Possession) 等の技術を導入し、アクセストークンを特定のクライアントの公開鍵と結びつける。これにより、万が一CORSが突破されても、トークン自体が別のオリジンでは無効化される。
3. 耐量子暗号への備え: 将来的に通信の暗号化強度が突破された際、オリジンベースの制限だけでは不十分になる。TLS 1.3の利用を強制し、鍵交換アルゴリズムとして耐量子暗号(Kyber等)への移行準備を進めるべきだ。
—
結びに:エンジニアとしての矜持
セキュリティとは、境界線をどこに引くかの美学だ。CORSポリシーを単なる「作業」として片付けるのではなく、あなたのAPIが「誰に対して、どの程度の信頼を置いているのか」を明確に定義する「境界の言語化」だと捉えてほしい。
「動けばいい」というコードは、いずれ誰かのインシデントの種になる。我々プロフェッショナルは、複雑なWeb標準の仕様を逆手に取り、攻撃者が入り込む余地をミリ単位で削り取る。それが、デジタル空間における我々の責務だ。
次は、プリフライトリクエストのキャッシュ汚染と、CDNレベルでのキャッシュキー戦略について深掘りしよう。技術は常に進化するが、境界を守るという本質は変わらない。
コメント