【CORS・SOP編】ブラウザの境界線を突破する手口と守り方|CTF思考フレームワーク #10
こんにちは、アンペンです!
前回は、画面を経由しないAPIならではの攻撃面と守り方を見ました。
今回は、ブラウザが標準で持っている境界線、SOP(同一オリジンポリシー)とCORSを扱います。CORS設定の誤りが、サイト間でデータが漏れる入口になる仕組みを見ていきましょう。

CORSってよく聞くけど、結局なにを守ってるの?

ブラウザの中で『別サイト同士の盗み見』を防ぐルールがSOP。CORSはそれを必要な範囲だけ緩める仕組みなんだ。
Web開発を少しでもかじった人なら、コンソールに赤字で出る『CORSエラー』に泣かされた経験があるかもしれません。「なんで別のサイトのデータが読めないの!」とイラッとするあのルール、実はあなたのブラウザがあなたを守ってくれている証拠なんです。今日は、その“見えない壁”SOPと、それを安全に開けるための仕組みCORSを、ビルのフロアにたとえてほどいていきましょう。
SOP(同一オリジンポリシー)は、別オリジンのデータをJavaScriptから読まれない基本ルールです。CORSはそれを限定的に緩める仕組みで、ワイルドカード許可やcredentials併用などの設定ミスが、サイト間データ漏洩や乗っ取りの入口になります。
この記事で分かること
- SOPとCORSの関係(基本ルールと例外)
- CORS設定ミスから生まれる代表的なリスク
- 演習環境での観察方法と、守る側の基本対策
📖 はじめてのWebセキュリティ #10|CORS・SOP編
ブラウザの内側にある「サイト間の壁」を題材に、壁を緩めすぎたときに何が起きるかを学びます。 シリーズ一覧を見る →
⚠️ 大事なお約束
この記事の確認は、CTF・公式ラボ・自分で作った検証環境だけで行ってください。実在するサービスのAPIに対しオリジン詐称や認証情報併用のテストを行う行為は、不正アクセス等に該当する可能性があります。
SOPとCORS:ブラウザの「壁」と「許可された通路」
ブラウザは標準で、違うオリジン(プロトコル+ホスト+ポートの組み合わせ)同士でデータを直接読み合えないように制限しています。これがSOP(同一オリジンポリシー)です。
でも、SaaSやマイクロサービスのように「正規に別オリジンへAPIを呼びたい」場面もあります。そこで、サーバー側が「このオリジンからのアクセスは許可する」と応答ヘッダで明示する仕組みがCORSです。
ここで大事なのは、許可を出すのは“サーバー自身”だということ。攻撃者が「自分を許可して」と言っても通りません。サーバーが応答ヘッダで『このオリジンならOK』と名乗って、初めてブラウザは壁を緩めます。逆に言えば、このサーバー側の“許可リスト”の書き方を間違えると、本来通すべきでない相手まで通してしまう——CORSの事故は、ほぼここから起きるんです。
なぜブラウザはこんな“お節介”な壁を作っているのでしょう。想像してみてください。あなたがネット銀行にログインしたまま、別タブで知らないサイトを開いたとします。もしこの壁がなかったら、その怪しいサイトのスクリプトが、あなたの銀行タブの中身を勝手に読めてしまう。それはまずいですよね。だからブラウザは『別オリジンのデータは、勝手に読ませない』というルール(SOP)を、最初から全サイトにかけてくれているんです。
図解:同一オリジンと別オリジンの違い

同じオリジンからのリクエストと、別オリジンからのリクエストでは、ブラウザの扱いが大きく異なります。

あるビルには、フロアごとに別のテナントが入っています。基本的に、テナント間のドアには鍵がかかっていて、自由に出入りできません。これがSOPです。一方、業務提携しているテナント同士は、特定のドアだけ鍵を共有して行き来できるようにします。これがCORSのイメージです。鍵をうっかり「誰でも」「常時」にしてしまえば、ビル全体の情報が筒抜けになってしまいます。
ここで覚える用語:オリジン
「プロトコル + ホスト名 + ポート番号」の組み合わせのことです。 https://example.com と http://example.com はプロトコルが違うので別オリジン、 https://api.example.com もホストが違うので別オリジンになります。
『オリジン』の感覚は、最初ちょっとつまずきやすいところ。ポイントは“プロトコル・ホスト・ポートのどれか一つでも違えば、別物として扱われる”ことです。同じ example.com でも、httpとhttpsは別。 www が付くだけでも別。人間の目には「同じサイトじゃん」と見えても、ブラウザにとっては“別の建物”——この厳密さこそが、壁を正しく機能させる土台になっています。
CORS設定ミスから生まれる代表的な問題
CORSの事故は、たいてい“壁を緩めすぎる”ことから起きます。代表的なミスは3つ。『誰でもOKにしてしまう(ワイルドカード)』『相手の名乗りをそのまま信じて許可する(Originエコー)』『名前の一部が合っていればOKにする(末尾一致)』。どれも“親切のつもりで鍵を配りすぎた”状態です。一つずつ見ていきましょう。
よくある危険な設定パターン

- Allow-Origin: * と credentials併用:あらゆるサイトからCookie付きでデータを読まれる(本来ブラウザが拒否する組み合わせだが、誤実装で抜けることがある)
- リクエストのOriginをそのままエコーバック:攻撃者サイトのOriginをそのまま許可してしまい、事実上ホワイトリストが効かない
- ホスト末尾だけで判定:「example.com で終わるなら許可」のような甘い判定で、 evilexample.com も通してしまう
これらの設定は、利用者がログイン中の状態であれば、攻撃者の用意したサイトを開かせるだけで個人データが盗まれる入口になります。
この攻撃の不気味なところは、利用者が“何も悪いことをしていない”のに被害に遭う点です。たとえばネット通販にログインしたまま、たまたま開いた攻撃者のサイト。そのページに仕込まれたスクリプトが、裏でこっそり通販サイトのAPIを叩く。もしCORSがガバガバなら、ブラウザは「許可されてるならどうぞ」とデータを渡してしまい、あなたの注文履歴や住所が攻撃者の手に——。リンクをクリックすらしていないのに、です。だからこの“壁”の設定は、本当に慎重でなければいけません。
では、自分のAPIがどんな“許可の名札”を返しているか、のぞいてみましょう。開発者ツールで応答ヘッダを見るだけなので簡単です。ただし、他人のサービスにオリジンを偽って投げるのはNG。あくまで自分のラボ・自分のAPIで、 Access-Control-Allow-Origin がどう返るかを観察してください。それだけで、設定の良し悪しがぐっと見えてきます。
CTFでやってみよう:CORSヘッダを観察する
自分の検証環境APIで、CORSヘッダの値を観察しよう
目的は別サイトを攻撃することではなく、「自分のAPIがどんなオリジン許可ヘッダを返しているか」を理解することです。
- CTFや自分の検証環境のAPIエンドポイントを開発者ツールで叩く
- 応答ヘッダの
Access-Control-Allow-OriginとAccess-Control-Allow-Credentialsを確認する - Origin ヘッダの値を変えてリクエストし、応答のAllow-Origin がどう変わるか比較する
- Allow-Origin が
*や任意の値をそのまま返していないか観察する - プリフライト(OPTIONS)リクエストの応答も合わせて確認する
守りの考え方はとてもシンプルで、『標準は閉じたまま、必要な分だけ名指しで開ける』。ここで、よくある疑問に答えておきましょう。

面倒だから Allow-Origin を * にして全部許可しちゃダメなの?

気持ちは分かるけど、それは玄関の鍵を開けっ放しにするのと同じだよ。とくにCookie(ログイン情報)を伴うAPIで * を使うと、世界中のどのサイトからでもあなたの利用者のデータが読めてしまう。だから許可するのは“本当に必要なオリジンだけ”を名指しで。面倒でも、ここは横着しちゃいけないところなんだ。
守る側なら、CORSは「最小許可」の原則で組み立てよう
CORSの基本は、「必要なオリジンだけを明示的に許可する」です。ワイルドカードや動的反映を避け、許可した範囲だけが緩むように設計します。
- Access-Control-Allow-Originはホワイトリストで明示し、
*は使わない(認証情報を含むAPIでは特に厳禁) - クライアントから受け取った Origin を、検証せずそのまま返さない
- Access-Control-Allow-Credentials を有効にする場合は、Originを必ず1つの厳密なホストに固定する
- ホスト判定は完全一致で行う(末尾一致や部分一致は使わない)
- 必要なHTTPメソッド・ヘッダだけを Allow-Methods/Allow-Headers で限定する
- 本番ではCSPと併用し、想定外の外部スクリプト読み込みを抑制する

CORSは「全部許可」じゃなくて『必要な分だけ開ける』が基本なんだね。

そう。SOPは『標準で閉じる』、CORSは『例外的に開ける』。順序を間違えないのがポイントだよ。
ここまでをひと言で言うと、『SOPは標準で閉じる、CORSは例外的に開ける』。この順番がすべてです。まず全部閉じておいて、どうしても必要な扉だけを、相手を名指しして、最小限だけ開ける。開けすぎないことが、そのまま守りになります。
まとめ:CORSは「壁の例外」だから慎重に
- SOPはブラウザの基本ルール。違うオリジンのデータは読めない
- CORSは例外を許可する仕組み。設定ミスはそのまま漏洩に直結する
- 危険なパターンは「Origin: *」「Originエコー」「末尾一致判定」
- 守る側はホワイトリスト+完全一致+credentials厳格化の3点を徹底する
今日の持ち帰りは『壁は、緩めるときこそ慎重に』です。SOPという便利な壁は、ブラウザが最初から用意してくれています。問題が起きるのは、たいてい人間がそれを“緩めすぎた”とき。ホワイトリストで名指し・完全一致で判定・認証情報の併用は厳格に——この3つを守れば、サイト間の壁は頼れる味方であり続けてくれます。
次回は、サーバーが自分自身や内部ネットワークに向けて意図せずリクエストを出してしまう問題、SSRFとLFIを扱います。サーバを「内側から覗かせる」攻撃と守り方を見ていきましょう。
