Webアプリケーションには、外部サービスと連携するためにURLへHTTPリクエストを送る機能が実装されていることがあります。
例えば次のような機能です。
- 外部APIからデータを取得する
- RSSフィードを読み込む
- Webhookを送信する
- 外部画像を取得する
こうした機能は便利ですが、実装によってはサーバー自身が攻撃者の指定したURLへアクセスしてしまうことがあります。
この問題はSSRF(Server-Side Request Forgery) と呼ばれる脆弱性です。
SSRFでは、攻撃者がWebアプリケーションを経由して内部ネットワークや管理画面へアクセスできてしまうことがあります。
この記事では、PortSwiggerのWeb Security Academyラボ「Basic SSRF against the local server」を例に、SSRFの基本的な仕組みを整理します。
さらに、WordPressの構造に置き換えながら、どのような場面でSSRFが発生する可能性があるのかも解説します。
SSRFとは何か
SSRF(Server-Side Request Forgery)は、サーバーに任意のURLへリクエストを送らせる攻撃です。
Webアプリケーションは、外部サービスと連携するためにHTTPリクエストを送ることがあります。例えば次のような機能です。
- 外部APIの取得
- RSSの取得
- Webhookの送信
- 外部画像のダウンロード
しかし、ユーザー入力のURLをそのまま取得する実装になっている場合、攻撃者は任意のURLへサーバーをアクセスさせることができます。
これがSSRFです。
SSRFの基本│なぜ内部サーバーにアクセスできるのか
SSRFの本質は、攻撃者が直接アクセスできない内部リソースへ、Webアプリケーションを経由してアクセスすることです。

外部ユーザーは localhost や内部ネットワークへ直接アクセスできません。
しかしWebアプリケーションは内部ネットワークへアクセスできることがあります。
SSRFは、このアクセス権限の差を悪用する攻撃です。
インターネットと内部ネットワークの構造
多くのWebシステムでは、次のようなネットワーク構造になっています。

この構造では
- 外部ユーザー → 内部ネットワークはアクセス不可
- Webサーバー → 内部ネットワークはアクセス可能
という状態になります。
SSRFは、この仕組みを利用した攻撃です。
ラボ「Basic SSRF against the local server」の概要
今回のラボは、Basic SSRF against the local serverです。
このアプリケーションには在庫確認機能(Stock Check) が存在します。
商品ページで「Check stock」をクリックすると、アプリケーションは内部システムから在庫情報を取得します。
処理の流れは次のようになっています。

このとき、在庫APIのURLはstockApi パラメータで指定されています。
SSRF攻撃はどのように実行されるのか
Burp Suiteでリクエストを確認すると、次のパラメータがあります。
stockApi=アプリケーションはこのURLを取得して在庫情報を表示しています。
つまり次のような処理です。
fetch(stockApi)ここでURLを書き換えることが可能です。
localhostへアクセスするSSRF
まず /admin にアクセスすると、
Access deniedとなり、管理画面には入れません。
しかし stockApi を次のように変更します。
stockApi=http://localhost/adminするとWebアプリケーションがlocalhostへリクエストを送信し、管理画面のHTMLが返ってきます。
管理ユーザー削除
管理画面HTMLを確認すると、次のURLが見つかります。
http://localhost/admin/delete?username=carlosこれを stockApi に指定します。
stockApi=http://localhost/admin/delete?username=carlosするとサーバーが内部管理画面へアクセスし、ユーザー carlosが削除されます。
これでラボは解決です。
なぜこのラボでSSRFが成立するのか
このラボでは、在庫確認機能がURLを指定してデータを取得する仕組みになっています。
つまり次のような処理です。
stockApi = user_input
response = fetch(stockApi)ここで問題になるのは、URLの検証が行われていないことです。
本来は次のような制限が必要です。
- localhost禁止
- 内部IP禁止
- APIドメインの制限
しかしこのラボでは、ユーザー入力URLをそのまま取得してしまいます。
よくあるSSRF攻撃パターン
SSRFはさまざまな形で利用されます。
localhost SSRF
今回のラボのように、
http://localhostへアクセスさせるパターンです。
管理画面や内部サービスが対象になります。
内部ネットワークSSRF
次のような内部IPをスキャンする攻撃です。
http://192.168.x.x社内システムや内部APIが対象になります。
クラウドメタデータSSRF
クラウド環境では、次のURLが重要です。
http://169.254.169.254ここには、
- IAMキー
- クラウド設定
などの機密情報が存在する場合があります。
WordPressに置き換えるとSSRFはどこで起きるのか
WordPressでも外部URLを取得する機能は多く存在します。
例えば次のようなケースです。
外部API取得
wp_remote_get()RSS取得
fetch_feed()Webhook
外部サービスへのHTTPリクエスト。
外部画像取得
URLを指定して画像をダウンロードする機能。
もしユーザー入力をそのままHTTPリクエストに使用すると、SSRFが発生する可能性があります。
開発者視点でのSSRF対策
SSRFを防ぐためには、サーバーがアクセスできるURLを制御することが重要です。
ドメイン制限(許可リスト)
アクセス可能なドメインを限定します。
allowed_domains = ["api.example.com"]localhost / 内部IPを禁止
次のアドレスはブロックする必要があります。
- localhost
- 127.0.0.1
- 内部IP
- 169.254.169.254
リダイレクトの検証
リダイレクトを利用して内部URLへ誘導される場合があります。
そのため、
- リダイレクトを制限
- リダイレクト先URLの再検証
が必要です。
ユーザー入力URLを使わない設計
可能であれば、
- URLを固定
- IDでAPIを指定
などの設計にする方が安全です。
SSRFはなぜ見つけにくいのか
SSRFは他の脆弱性と比べて、発見が難しいことが多いと言われています。
その理由は、攻撃がサーバー側で実行されるためです。
通常の攻撃では、攻撃者のブラウザとWebサーバーの通信を確認すれば挙動を把握できます。
しかしSSRFの場合、実際のリクエストは次のような流れになります。
攻撃者 → Webアプリケーション → 内部サーバー
つまり、内部サーバーへのアクセスは攻撃者の環境からは直接確認できません。
そのため、
- レスポンスの変化
- エラーメッセージ
- タイミングの違い
などを手がかりに挙動を推測する必要があります。
ログからSSRFの兆候を見つける
SSRFはサーバー側で実行されるため、サーバーログに痕跡が残ることがあります。
例えば次のようなログです。
- 内部アドレスへのHTTPリクエスト
- localhostへのアクセス
- 内部APIへの不自然なアクセス
Webサーバーや内部サービスのログを確認することで、SSRF攻撃の兆候が見つかる場合があります。
SSRFを発見するためのセキュリティ診断チェックポイント
SSRFはURLをサーバーに送らせる機能を見つけることがスタートです。
以下の手順で調査すると効率よく発見できます。
① 外部URLを受け取る機能を探す
まずは、ユーザーがURLを入力・指定できる機能を探します。
チェック対象
- API連携機能(URL指定)
- RSSフィード取得
- Webhook送信先
- 画像URL入力
- 外部データ取得機能
見るポイント
- フォーム入力欄にURLがある
- パラメータにURLっぽい値がある(例:
url=,api=,feed=)
ポイント
「URLを入力できる場所=SSRF候補」と考える
② リクエスト内容を確認する(Burp or DevTools)
次に、その機能が実際にどんなリクエストを送っているか確認します。
確認方法
- Burp Suiteでリクエストをキャプチャ
- またはブラウザのDevTools(Networkタブ)
見るポイント
stockApi=のようなURLパラメータがあるか- サーバー側でURLを取得している形跡
例
stockApi=http://example.com/apiこの時点で書き換え可能なら怪しい。
③ URLを書き換えて挙動を確認する
ここがSSRF診断の核心です。
実際にURLを書き換えて、サーバーの挙動を確認します。
localhostアクセスを試す
http://localhost
http://127.0.0.1チェックポイント
- レスポンスが変わるか
- HTMLが返ってくるか
- エラー内容が変わるか
内部IPを試す
http://192.168.0.1
http://10.0.0.1反応があれば内部ネットワークアクセスの可能性あり。
クラウドメタデータを試す
http://169.254.169.254AWSなどでは重要情報が取れる可能性あり。
④ レスポンスの変化を観察する
SSRFは見た目で分かりづらいので、変化を注意深く見ます。
チェックポイント
- レスポンス内容が変わる
- ステータスコードが変わる
- タイムアウトが発生する
- エラーメッセージが変わる
例
- 通常:
Invalid URL - localhost指定:HTMLが返る → SSRFの可能性
⑤ リダイレクトの挙動を確認する
フィルタ回避のために重要なポイントです。
テスト方法
- 外部URL → 内部URLへリダイレクトさせる
例
http://attacker.com → http://localhost/adminチェックポイント
- リダイレクト先までアクセスされるか
⑥ ログから異常な通信を探す
SSRFはサーバー側で実行されるため、ログにヒントが残ることがあります。
見るべきログ
- Webサーバーログ
- アプリケーションログ
チェックポイント
- localhostへのアクセス
- 内部IPへの通信
- 不自然な外部リクエスト
SSRF対策(WordPress・Webアプリ共通)
SSRFを防ぐためには、サーバーがアクセスするURLを制御することが重要です。
- ユーザー入力のURLをそのまま使用しない
- アクセス可能なドメインを制限する(許可リスト)
- localhost や内部IPへのアクセスを禁止する
※具体的な対策方法は別記事で詳しく解説します。
WordPressでSSRFが発生しやすい実装例
WordPressでは、外部URLへリクエストを送るための関数が用意されています。
注意が必要な関数
wp_remote_get()wp_remote_post()fetch_feed()
これらは便利な反面、ユーザー入力のURLをそのまま渡すとSSRFの原因になります。
実際の危険なコード例
例えば、次のような実装です。
$url = $_GET['url'];
$response = wp_remote_get($url);このコードでは、ユーザーが指定したURLに対して、サーバーがそのままHTTPリクエストを送ってしまいます。
なぜ危険なのか
この状態では、攻撃者が次のようなURLを指定できます。
http://localhosthttp://127.0.0.1http://192.168.x.x
その結果、サーバーが内部ネットワークへアクセスしてしまい、管理画面や内部APIに到達する可能性があります。
実際のチェック方法
WordPressサイトを調査する際は、次のポイントを確認します。
- プラグイン内で
wp_remote_get()が使われていないか - ユーザー入力(GET / POST)をそのままURLに使っていないか
- URLの制限(ドメイン制限・IP制限)があるか
ポイント
ユーザー入力 → URL → HTTPリクエスト
この流れがあればSSRFを疑う。
まとめ
SSRFは、サーバーに任意のURLへアクセスさせる攻撃です。
今回のラボでは、
- URL指定の在庫API
- URL検証不足
- サーバーの内部アクセス権限
という条件が揃うことでSSRFが成立しました。
WordPressでも、
- API取得
- RSS取得
- Webhook
などの機能では同様の問題が発生する可能性があります。
外部URLを扱う機能を実装する場合は、アクセス可能なURLを厳格に制御することが重要です。
