複合チャレンジ|SSRF×OAuth×XXEを繋ぐ侵入経路
ここまでの8話で、1つひとつの脆弱性クラスを個別に体験してきました。第9話では、その中から第2話のSSRF・第7話のOAuth・第8話のXXEという3つを取り出し、1本の侵入シナリオに繋ぎます。単体では「内部情報がちょっと漏れる」程度の脆弱性が、連鎖すると最終的に最高機密へ到達してしまう——現場の侵害事例で実際に起きている「攻撃チェーン」を、自分の手で組み立てます。
📋 目次
🔗 なぜ「単発の脆弱性」より「連鎖」が怖いのか
中リスクが3つ連なると、結果は最高リスクになる
「これ単体ではたいした影響はない」が積み重なるとき
脆弱性診断の現場では、1つひとつの指摘に「重大度:中」のようなランクが付きます。SSRFで内部の設定が少し見える、OAuthの検証がやや緩い、XMLインポートにXXEがある——どれも単体なら「いつか直そう」で済まされがちです。しかし攻撃者は、これらを別々の問題とは見ません。「Aで得た情報でBに入り、Bで得た権限でCを破る」という1本の道として繋ぎます。こうして中リスク3つが、最高機密の流出という最大の結果を生みます。
実際の大規模侵害の報告書を読むと、ほとんどが「単一の致命的な穴」ではなく「複数の中程度の弱点の連鎖」で構成されています。攻撃者にとって重要なのは、個々の脆弱性の派手さではなく、それらが繋がって最終目標(機密データ、管理者権限、ドメイン全体の掌握など)に届くかどうかです。だからこそ防御側も、脆弱性を単体の重大度だけで評価するのではなく、「これが他のどの弱点と繋がりうるか」という連鎖の視点で見る必要があります。
この話の前提知識(3話分を使います)
今回は3つの技術を繋ぎます。各技術の詳しい仕組みは、それぞれの回を読み返すとスムーズです。
- 上級編 第2話「SSRFでクラウド内部に侵入|メタデータエンドポイントの罠」
- 上級編 第7話「OAuth/SSOの落とし穴|認可コード窃取とredirect_uri検証バイパス」
- 上級編 第8話「XXEで内部ファイルを読み取る|XML外部エンティティの悪用」
本話の舞台は、これまでの回に登場した架空のアプリ「ToDoループ」と認可基盤「Aurora ID」です。3つの脆弱性が同じシステムの中に同居しているとき、攻撃者がどう連鎖させるのかを体験します。
🗺️ 今回の攻撃チェーンの設計図
3つの脆弱性が、バトンを渡すように繋がる
今回の侵入は、次の3ステップで進みます。重要なのは、各ステップの「出力」が、次のステップの「入口」になっている点です。1つ目で手に入れた情報がなければ2つ目は始められず、2つ目で得た権限がなければ3つ目には届きません。これが攻撃チェーンの基本構造です。
チェーンは「弱い輪」を1つずつ手繰る
攻撃者はいきなり最終目標を狙うのではなく、まず一番外側の弱い輪(ここではSSRF)を見つけ、そこで得た手がかりを使って次の輪へと進みます。1ステップごとに少しずつ内側へ入っていくこの動きは、まさに鎖を手繰り寄せるようなものです。逆に言えば、どこか1つの輪さえ断ち切れれば、その先のチェーンは成立しません。これは後の防御の節で重要になります。
🔍 1つの出力が、次の入口になる
「単体での影響は小さい」という評価が見落とすもの
SSRF単体の影響は、しばしば「内部の情報がいくらか見える」程度に評価されます。しかし、その「いくらか見える情報」の中に、OAuthクライアントの設定(client_idや、検証が緩い登録redirect_uri)が含まれていたらどうでしょうか。SSRFの出力は、そのままOAuth攻撃の入力になります。同様に、OAuth攻撃で得た管理者トークンは、本来は管理者しか触れないXMLインポート機能への入場券になります。こうして各脆弱性の「出口」と「入口」が噛み合うと、全体として1つの大きな攻撃が成立します。
診断レポートを「点」ではなく「線」で読む
脆弱性診断の報告書には、たいてい脆弱性が「点」として箇条書きされています。熟練した攻撃者と防御者は、その点と点を結ぶ「線」を見ます。「この情報漏洩は、あの認証不備の前提条件を満たさないか?」「この権限昇格は、あのファイル読み取りの入口にならないか?」——個別の重大度ランクだけを見ていると、この線が見えません。複合チャレンジは、その線を引く訓練そのものです。
次の実践チャレンジでは、3つのステージを順に攻略します。ステージ1の出力(盗んだクライアント情報)がステージ2の入力になり、ステージ2の出力(管理者トークン)がステージ3への入場券になります。前の話を思い出しながら、1本の侵入経路を組み立ててください。なお、すべてのステップは架空のシステムを安全に再現したもので、実際のネットワーク通信やファイルアクセスは一切発生しません。
💻 実践チャレンジ:3つの脆弱性を繋いで最高機密に到達せよ
SSRFで手がかりを得て、OAuthで権限を奪い、XXEで機密を読む
架空のサービス「ToDoループ」には、第2話で学んだSSRF、第7話のOAuth検証不備、第8話のXXEが、同じシステムの中に同居しています。3つのステージを順に攻略し、最終的に最高機密ファイルのフラグに到達してください。各ステージをクリアすると、次のステージが解放されます。
ステージ1→2→3の順に解放されます。3つすべてクリアした時点でスコアが確定します。
📊 ステージ進捗: 0/3|挑戦回数: 0回
ToDoループには「URLプレビュー」機能があり、サーバーが指定URLを取得します。内部メタデータサービスはhttp://169.254.169.254/にありますが、WAFがこの文字列をブロックします。WAFをすり抜けて内部メタデータに到達し、応答の中の合言葉(passphrase)を入力してください(例: SSRF-IMDS-LEAK)。
$ ToDoループ – URLプレビュー機能(サーバーが代理でGETする)
WAFは「169.254.169.254」という文字列そのものを検知しています。同じIPアドレスを、別の表記で書けないでしょうか。第2話で扱った「10進数表記」を思い出してください。
169.254.169.254を10進数1つで表すと2852039166です。http://2852039166/と入力してみてください。WAFは文字列を検知できず、サーバーは正規化して同じ内部IPに接続します。
ステージ1のメタデータから、管理者用OAuthクライアントの情報が手に入りました。redirect_uriの検証は「前方一致」です。前方一致は通過するのに、実際の遷移先はadmin.todoloop.exampleではない、というredirect_uriを作って認可コードを横取りし、表示された合言葉を入力してください(例: OAUTH-ADMIN-TOKEN)。
ステージ1で入手した管理者クライアント情報: client_id = todoloop-admin redirect_uri検証 = 前方一致(prefix-match) 登録redirect_uri = https://admin.todoloop.example/cb
$ Aurora ID – 認可リクエストのredirect_uriテスター
第7話と同じサブドメイン混乱を使います。https://admin.todoloop.example.attacker.example/stealのように、登録プレフィックスをそのまま先頭に置きつつ、実際のホストは自分のドメインにします。
管理者トークンを手に入れたので、管理者専用のXML設定インポートが使えるようになりました。外部エンティティを使って最高機密ファイルfile:///srv/todoloop/secret/master.flagを読み出し、中のFLAG=の値を入力してください。
$ ToDoループ – 管理者専用XML設定インポート(認証済み: todoloop-admin)
外部エンティティのSYSTEM "file://..."の部分をfile:///srv/todoloop/secret/master.flagに書き換えてパースしてください。結果の中のFLAG=の右側がフラグです。
🛡️ 防御側の視点|チェーンはどこか1箇所で断ち切れる
すべてを完璧にできなくても、1つの輪を断てば連鎖は止まる
攻撃チェーンの怖さは「3つ繋がると最大の被害になる」ことですが、防御側にとっての希望もそこにあります。チェーンは、構成する輪のどれか1つでも断ち切れれば成立しません。3つすべてを完璧に塞げなくても、最も直しやすい1箇所を確実に塞ぐだけで、その経路は崩れます。今回のチェーンなら、次のどれか1つでも実施されていれば最高機密への到達は防げました。
- ①の輪を断つ(SSRF対策):URL取得機能で内部アドレスへのアクセスを宛先IPの正規化後に判定して拒否する。文字列ブロックリストではなく、解決後のIPで判断する
- ②の輪を断つ(OAuth対策):redirect_uriを前方一致ではなく完全一致で検証する。これだけで盗んだクライアント情報があっても認可コードは横取りできない
- ③の輪を断つ(XXE対策):XMLパーサーで外部エンティティとDTDを無効化する。管理者権限を奪われても、機密ファイルの読み出しは成立しない
- 多層防御の発想:1つの対策に頼らず、複数の層で備える。どこか1層が破られても、次の層でチェーンが止まる
- 連鎖の視点で診断する:個々の脆弱性の重大度だけでなく、「これは他のどの弱点の入口・出口になりうるか」を評価し、チェーンの起点になりやすい箇所を優先的に塞ぐ
「完璧」でなくてよい。1つの輪を確実に断つ
すべての脆弱性を同時にゼロにするのは現実には困難です。だからこそ、攻撃を「チェーン」として捉え、最も断ち切りやすい輪を見極めて確実に潰すという発想が有効です。1つの確実な対策が、その先に連なるはずだった被害をまとめて防ぎます。
単体では中程度に見える脆弱性も、繋がれば最大の結果を生む——そして、その鎖はどこか1箇所で断てる。これが複合チャレンジから持ち帰ってほしい、攻守両面の最も重要な視点です。次のセクションでまとめます。
📝 まとめ+FAQ+次回予告
点を線で結ぶと、攻撃の全体像が見える
第9話では、SSRF・OAuth・XXEという3つの脆弱性を1本の侵入経路に繋ぐ複合チャレンジを体験しました。各ステップの出力が次の入口になる連鎖の構造と、その鎖がどこか1箇所で断てることを、攻守両面から確認しました。
・実際の侵害の多くは「単一の致命傷」でなく「中リスクの連鎖」で起きる
・SSRFの出力(クライアント情報)→OAuthの入力、OAuthの出力(管理者トークン)→XXEの入場券、と繋がる
・脆弱性は単体の重大度でなく「他のどの弱点の入口・出口になるか」という連鎖の視点で評価する
・チェーンは構成する輪のどれか1つを断てば成立しない=多層防御が有効
Q. 実際の侵害でも、こうした複数脆弱性の連鎖は起きていますか?
はい。大規模な侵害事例の報告書の多くは、単一の致命的脆弱性ではなく、複数の中程度の弱点を連鎖させた攻撃チェーンとして記述されています。SSRFからクラウド認証情報を窃取し、それを足がかりに横展開する、といった連鎖は代表的なパターンです。
Q. このチャレンジは実際のネットワークやファイルにアクセスしていますか?
いいえ。SSRFのURL取得・OAuthの認可サーバー・XXEのファイル読み取りは、すべてページ内のJavaScript関数とあらかじめ用意した架空の対応表だけで再現しています。実際の通信・ファイルアクセス・外部サービスへの接続は一切ありません。
Q. なぜ実在のサービス名やIPではなく架空のものを使うのですか?
実在のサービスやインフラを対象にすると、本物の攻撃手順の解説と誤認されるおそれがあるためです。本話では概念と連鎖の構造を正確に保ったまま、架空のアプリ・架空の認可基盤・学習用の予約済みアドレスだけで構成しています。
Q. 進捗やスコアの情報はどこかに送信されますか?
送信されません。すべてブラウザのlocalStorage(あなたの端末内)だけに保存され、外部のサーバーには一切送信されません。入力したURLやXMLもどこにも送られず、ページ内で処理されるだけです。
レッドチーム演習|偵察から目的達成までの一気通貫
いよいよ最終回。これまでの全話で学んだ技術を総動員し、偵察・侵入・権限昇格・横展開・目的達成という、レッドチーム演習の一連の流れを体験します。
📚 参考情報
- OWASP Top 10(A01/A05/A10 ほか、複数カテゴリにまたがる連鎖)
- MITRE ATT&CK(攻撃の段階を連鎖として捉えるフレームワーク)
- 各種インシデントレポートにおける攻撃チェーン(kill chain)の分析


コメント