はじめに
SSRF(Server-Side Request Forgery) とは、
攻撃者がサーバーに意図しないリクエストを送らせることで、
本来アクセスできない内部リソース(社内ネットワーク、クラウドメタデータなど)へ到達させる攻撃手法です。
「ユーザーが入力したURLを、サーバーが代わりに読み込む」ような機能が狙われます。
攻撃の仕組み
たとえばWebアプリに以下のような機能があるとします:
https://example.com/fetch?url=https://news.com/article.html
サーバー側が url
パラメータの内容を取得してレスポンスを返すようになっている場合、
攻撃者はこう書き換えます:
https://example.com/fetch?url=http://169.254.169.254/latest/meta-data/
このIPアドレス(169.254.169.254)は、
AWSやGCPなどクラウドのインスタンスメタデータサーバーへのアクセス先。
サーバーがこれを内部的にリクエストしてしまうと、
攻撃者は認証トークンや機密情報を奪うことが可能になります。
Types of SSRF(分類)
主な分類
-
Regular / Reflected SSRF
- サーバーが取得したレスポンス(内部ページやメタデータ)を攻撃者に返す。攻撃者は即座に情報を確認できる
- 例: レスポンス本文にメタデータや内部HTMLが返るケース
-
Blind SSRF(非表示型)
- サーバーは内部リクエストを実行するが、そのレスポンスは攻撃者に返らない。直接的な情報漏えいはないが、サーバー経由で内部サービスにアクションを与えられる
- 検出にはOOB(Out-Of-Band)チャネルが必要(DNS回線やコールバックサービス等)
サーバー側の処理が、ユーザー入力を使って外部あるいは内部のURLへHTTP等のリクエストを発行する際に、その入力を悪用されて内部ネットワークやクラウドのメタデータなどに到達される脆弱性。攻撃者はサーバーを踏み台にして内部情報を取得したり、内部サービスを操作させたりする。
よくある派生パターン(実務で混乱しやすいもの)
-
OOB / Blind SSRF(DNS/HTTPコールバック方式)
- 攻撃者は自分の制御するドメインにDNSやHTTPリクエストを発生させ、コールバックで成功を確認する。セキュリティ検査で使うBurp Collaborator / Interactsh と同じ考え方
-
Second-order SSRF(2次型)
- 一度保存された(安全に見える)URLが後で別の処理によりサーバー側でフェッチされ、そのときにSSRFが発動するパターン。入力→保存→別処理のフローで発生しやすい
-
Port-scan via SSRF
- 内部ホストの特定ポートに順次アクセスして開いているサービスを探る。情報はレスポンスやタイミング差で推測されることがある(タイミング攻撃やエラーメッセージ利用)
-
SSRF → リソース操作 / RCE に発展
- 内部 API を叩いて認証なしで操作させる、あるいは内部サービスの未検証のエンドポイントを利用して間接的にコード実行につながるケースもある
よく使われる防御とその“抜け道”(概念的)
開発者が取る代表的対策はDeny List(ブラックリスト)とAllow List(ホワイトリスト)。しかし攻撃者は入力の異表現・DNSの振る舞い・リダイレクトなどを使って回避を試みる。
-
Deny List(ブラックリスト)の抜け道)
- 問題点:表現の多様性(IPの異表記、16進/8進/10進表現、IPv6記法、DNSエイリアスなど)やサブドメインを使った回避
- 対策(概念):表現前の文字列検査だけでなく、DNS解決→得られたIPアドレスに対して判定すること
-
Allow List(ホワイトリスト)の抜け道)
- 問題点:ホワイトリスト照合がホスト名の文字列だけだと、許可系のドメイン名を起点に作られた複合サブドメインで回避されうる
- 対策:ホスト名の正規化(Punycode等)後に、最終的に解決するIPが“許可済み”かを確認する
-
Open Redirect を使ったバイパス
- 問題点:アプリの中に外部へリダイレクトする正当な仕組みがある場合、それを経由して任意の外部ドメインへつなげられると、外向き制約をすり抜けることがある
- 対策:リダイレクト先は厳格に検査し、サーバー側でフェッチする際はリダイレクトを自動追跡しないか、追跡しつつ毎段階で検査を行う
要点:表現(input)を検査するだけでなく、実際に接続される“実体(IP/ポリシー)”で判断せよ。これが防御の哲学。
実践的防御
高優先度(すぐやる)
- ホワイトリスト優先:外部フェッチは許可されたドメイン群のみ。
- DNS解決してIPをチェック:名前解決結果のすべてのIPを内部/リンクローカル/メタデータレンジ等と照合。
- メタデータアクセスのネットワーク制御:クラウド環境では IMDS(例:169.254.169.254)へのアクセスをネットワークレベルで遮断またはIMDSv2などで制限。
- アウトバウンドはプロキシ経由の強制:プロキシでACL・ログ・TLS検査を一元化。
- 自動リダイレクトを無効化:フェッチ時の自動リダイレクト追跡を無効化、追跡時は都度検査。
中優先度(設計的対策)
- スキーム制限(
http
/https
のみ許可、file:
gopher:
等を拒否) - 許可ポート制限(管理系ポートは許さない)
- IDN(国際化ドメイン名)をPunycodeに正規化して比較
- 保存→後フェッチ(second-order)ワークフローのレビュー
ネットワーク/運用(必須)
- Egress proxy + ネットワークACL を組み合わせた二重防御
- プロキシ/SIEMで外向き接続の監査ログとアラートを整備
- アプリケーション側ログで宛先ホスト名とIPの両方を残す
検出・テスト戦略(QA / ペネトレ向け、ただし許可必須)
重要:テストは必ず権限のある環境で実施すること。
- Blind SSRF 検出:DNS/HTTPのOOBチャネル(InteractshやBurp Collaborator)を利用して、サーバーからのコールバック発生有無を確認。
- Second-order の確認:ユーザー入力を保存するフロー/バッチ処理/別サービスが後でフェッチするパスを特定してテスト。
- 自動化テスト:CIで「危険そうなURLを拒否するユニットテスト」を作る(URL正規化、DNS解決→IP検査、スキームチェック等)。
- ブラックボックス/アプリ診断:ログを観察し、未承認の外向き接続や内部IPアクセス試行を検出するシナリオを作る。
ログ・監視(SIEM)で見るべき指標
- アプリからの宛先IPとホスト名の両方を保存
- 内部レンジへの接続試行で即アラート(閾値は環境で調整)
- 未知ドメインへの大量アクセス、または短期間に多数のDNS解決が発生した場合の異常検出
- プロキシログでのリダイレクトチェーンや失敗率の急増はブラインドSSRFの兆候になる
tryhackmeのSSRF Practical
問題 What is the flag from the /private directory?
答えはTHM{YOU_WORKED_OUT_THE_SSRF}です。
https://x.x.tryhackme.com/customers/new-account-page
にアクセスしてアバターを変更した後、ViewSourceを見ます。
では、もう一度リクエストしてみましょう。ただし、アバター値をプライベートに変更し、サーバーがリソースにアクセスしてIPアドレスブロックを通過できることを期待します。
エラーメッセージからわかるように、パスは/privateで始まることはできませんが、ご安心ください。このルールを回避する秘策がまだあります。ディレクトリトラバーサルを使って目的のエンドポイントに到達できます。アバターの値をx/../privateに設定してみてください。
最終、base64 String をもらいました。
<div class="avatar-image" style="background-image: url(data:image/png;base64,VEhNe1lPVV9XT1JLRURfT1VUX1RIRV9TU1JGfQ==)"></div>
デコードの後は
THM{YOU_WORKED_OUT_THE_SSRF}
まとめ
- SSRFは “表現”の多様性を突く攻撃。だから防御は表現の検査ではなく「接続先の実体(IP/ポリシー)」で行うことが肝
- 実装ではホワイトリスト+DNS解決→IP判定→プロキシ強制+ネットワークACLの三層防御がベストプラクティス
- Blind SSRFは見つけにくいが、OOB検出・監査ログ・プロキシログで相当程度検出できる
- CIにユニット/E2Eテストを組み込み、コードレビューで必須チェックにすること