
はじめに
あれは確か、3年くらい前だったかな。いや、もしかしたら4年前かもしれない。まあ、そのへんはどうでもいいんだけど、クライアントのWordPressサイトで、ちょっと変な挙動を見つけたんだよね。
最初は「なんだこれ?」って思って、ログを見てたら、内部ネットワークへのアクセスログが大量に残ってた。で、「え、これ誰がアクセスしてるの?」って焦った。心臓がバクバクした。
調べてみたら、プラグインの脆弱性を突かれて、SSRF攻撃を受けてたんだよね。で、「SSRF?なにそれ?」って思って、必死に調べた。正直、その時まで知らなかった。恥ずかしい話だけど。
Point(結論):
サーバーサイドリクエストフォージェリ(SSRF)攻撃は、サーバーに成り代わってリクエストを送信させる攻撃手法で、内部ネットワークへのアクセスやファイルシステムの読み取りなど、深刻な被害をもたらす可能性がある。WordPressではwp_safe_remote_get()などの「安全」と名付けられた関数でさえ、完全には安全ではなく、プラグインの実装次第で脆弱性が生じる。対策としては、ホワイトリスト方式の導入、入力検証の徹底、ネットワーク分離が重要だ。

SSRF攻撃って何?
SSRF攻撃について、ちょっと説明するね。
SSRF(Server-Side Request Forgery)っていうのは、サーバーサイド・リクエストフォージェリの略で、サーバーに成り代わってリクエストを送信させる攻撃手法なんだ。
これ、結構やばい。っていうか、本当にやばい。
具体的にどういう攻撃なの?
例えば、こういうシナリオを想像してみて。
あるWordPressサイトに、ニュースフィード機能があるとする。で、この機能は、外部のURLからデータを取得して、ページに表示するんだよね。
開発者は「URLをリクエストパラメータで受け取れたら便利だな」って思って、こんな実装にしちゃった。
<?php
$url = $_GET['newsUrl'];
$response = wp_safe_remote_get($url);
$body = wp_remote_retrieve_body($response);
echo $body;
?>これ、一見便利そうでしょ?でも、これが大問題なんだよね。
何が問題なの?
攻撃者は、このnewsUrlパラメータを自由に書き換えられるんだ。
例えば、こんなURLを送信できる。
http://example.com/news?newsUrl=http://192.168.1.1/adminサーバーが内部ネットワークの192.168.1.1/adminにアクセスしちゃう。これ、外部からは直接アクセスできない内部リソースなんだけど、サーバー経由だとアクセスできちゃうんだよね。
「これはヤバい」って思った。本当に。

SSRF攻撃で何ができちゃうの?
SSRF攻撃で、攻撃者は色々なことができちゃう。で、これが本当に怖い。
1. 内部ネットワークへのアクセス
攻撃者は、http://192.168.1.*みたいな内部ネットワークのアドレスを指定できる。で、ファイアウォールで保護された内部リソースにアクセスできちゃうんだよね。
これ、本当にやばい。っていうか、僕もこれで焦った。
2. ファイルシステムへのアクセス
file:///で始まるURLを指定されると、サーバー上のファイルを読み取られちゃう可能性がある。
処理系によっては、/etc/passwdとか、機密情報が入ってるファイルを読み取られちゃうこともある。で、「これは本当にマズい」って思った。
3. クラウドサービスのエンドポイント
AWSのメタデータエンドポイントhttp://169.254.169.254/にアクセスされると、認証情報やAPIキーを取得されちゃう可能性がある。
これが一番怖い。っていうか、これで実際に被害が出たケースもあるんだよね。
4. 情報改ざん
今回の例ではGETリクエストだけど、もしもPOSTなど副作用があるリクエストだったら、内部システムを操作されちゃう可能性がある。
「これは本当に危険だな」って思った。
5. 攻撃の踏み台
別のサービスへの攻撃の踏み台として悪用されることもある。

自分のサーバーが攻撃の踏み台にされるって、本当に嫌だよね。正直、これは避けたい。

WordPressにおけるSSRF脆弱性
WordPressにおけるSSRF脆弱性について、ちょっと詳しく説明するね。
wp_http_validate_url()の問題
2022年9月に、SonarSourceがパッチ未適用のWordPress Core Unauthenticated Blind SSRFに関するアドバイザリを公開したんだよね。
この脆弱性の根本的な原因は、wp_http_validate_url()関数がDNSリバインディング攻撃の影響を受けやすいことなんだ。
WordPressコア自体は直接影響を受けないんだけど、この関数を利用するプラグインは危険にさらされる。で、「これは結構深刻だな」って思った。
wp_safe_remote_get()は本当に安全?
WordPress公式ドキュメントには、こう書いてある。
「この機能は、HTTP リクエストが任意の URL に対して行われる場合に最適です。リダイレクトやリクエスト偽造攻撃を回避するために URL が検証されます。」
「安全」って名前がついてるから、「これ使えば大丈夫でしょ?」って思うよね。僕もそう思ってた。
でも、実は完全に安全じゃないんだよね。
なぜ安全じゃないの?
wp_safe_remote_get()のソースコードを見てみると、こうなってる。
function wp_safe_remote_get($url, $args = array()) {
$args['reject_unsafe_urls'] = true;
$http = _wp_http_get_object();
return $http->get( $url, $args );
}2行目で$args['reject_unsafe_urls']パラメータがtrueに設定されてて、URLを要求する前にユーザー入力がwp_http_validate_url()関数に渡される。
wp_http_validate_url()はDNS再バインディング攻撃に対して脆弱だから、検証にこの関数のみに依存する関数もすべて脆弱なんだよね。
「これは結構問題だな」って思った。正直、「安全」って名前がついてるのに、完全に安全じゃないって、ちょっと紛らわしいよね。
脆弱性の制限
この脆弱性には、いくつかの制限がある。
- プロトコルは
http://またはhttps://のみ - ポートは80、443、8080のいずれか
これらの制限内で内部ホストを要求することは可能なんだよね。

脆弱なプラグインコードの例
実際に脆弱なプラグインコードの例を見てみよう。
非盲検SSRF(Non-Blind SSRF)
<?php
require_once('wp-load.php');
$url = $_GET['url'];
$response = wp_safe_remote_get( $url );
$response = wp_remote_retrieve_body( $response );
echo $response;
?>これ、プラグインがユーザー入力をwp_safe_remote_get()に渡して、応答を表示してる。で、これは非ブラインド制限SSRFに対して脆弱なんだよね。
攻撃者は、内部リソースの内容を直接読み取れちゃう。で、「これはマズいな」って思った。
ブラインドSSRF(Blind SSRF)
<?php
require_once('wp-load.php');
$url = $_GET['url'];
$response = wp_safe_remote_get( $url );
$response_code = wp_remote_retrieve_response_code( $response );
if ($response_code == 200) {
echo "稼働中";
} else {
echo "ダウンしているか見つかりません!";
}
?>これ、プラグインがユーザー入力をwp_safe_remote_get()に渡しても、応答コード/ステータスのみを返してる。
これはブラインドSSRFに対して脆弱で、影響は内部ホストのポート80、443、8080のポートスキャンに限定される。
でも、これでも内部ネットワークの構成を調べられちゃうから、結構危険なんだよね。
その他の脆弱な関数
wp_http_validate_url()を使用する他の関数も同様に脆弱だ。
wp_safe_remote_request()wp_safe_remote_post()wp_safe_remote_head()
あと、ラッパー関数として機能し、ある程度脆弱な関数もある。
WP_REST_URL_Details_Controller::get_remote_url()download_url()wp_remote_fopen()WP_oEmbed::discover()
「これ、結構色々な関数が影響を受けるんだな」って思った。正直、ちょっと驚いた。

実際のプラグインの脆弱性事例
実際にSSRF脆弱性が発見されたプラグインの事例を紹介するね。
Broken Link Checker 2.4.2
2024年12月に、Broken Link Checkerのプラグインに関する脆弱性が発見された。
これはSSRFと呼ばれる問題で、プラグインがリクエストを出す際に、不正なリクエストを送信できちゃう脆弱性だった。
CVE番号は CVE-2024-10903。で、「これは結構有名なプラグインだから、影響範囲が広いな」って思った。
URL Media Uploader 1.0.0以前
WordPressプラグインのURL Media Uploaderにサーバサイドリクエストフォージェリ(SSRF)の脆弱性が発見された。
この脆弱性はバージョン1.0.0以前の全バージョンに影響する。CVE番号は CVE-2025-1662。
「これも結構深刻だな」って思った。
Ditty WordPress Plugin
Dittyプラグインに、認証なしでSSRF攻撃が可能な脆弱性が発見された。
CVE番号は CVE-2025-8085。で、これは認証なしで攻撃できるから、特に危険なんだよね。
内部リソースへのアクセスが可能になっちゃう。で、「これは本当にマズい」って思った。
Broken Link Notifier 1.3.0以前
Broken Link Notifierプラグインにも、SSRF脆弱性が発見された。
CVE番号は CVE-2025-6851。で、「Broken Linkチェック系のプラグインは、外部URLにアクセスする機能があるから、SSRF脆弱性が発生しやすいのかな」って思った。
SSRF攻撃への対策
SSRF攻撃への対策について、ちょっと説明するね。
1. ホワイトリスト方式の導入
許可されたURLのみアクセス可能にする。
ドメインやIPアドレスのホワイトリストを作成して、それ以外のアクセスを拒否する。
$allowed_domains = ['example.com', 'trusted-partner.com'];
$parsed_url = parse_url($url);
if (!in_array($parsed_url['host'], $allowed_domains)) {
die('許可されていないドメインです');
}これが一番確実な対策だと思う。僕もこれを使ってる。
2. 入力検証の徹底
URLの形式を厳密にチェックする。
- プロトコルの制限(http/httpsのみ)
- プライベートIPアドレスの拒否(192.168.x.x、10.x.x.x、127.0.0.1など)
- ループバックアドレスの拒否
$parsed_url = parse_url($url);
$ip = gethostbyname($parsed_url['host']);
// プライベートIPアドレスをチェック
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
die('プライベートIPアドレスへのアクセスは許可されていません');
}これも結構重要。っていうか、これをやらないとダメだよね。
3. ネットワーク分離
内部ネットワークとの分離を行う。
ファイアウォールの適切な設定で、Webサーバーから内部ネットワークへのアクセスを制限する。
これはインフラレベルの対策だけど、結構効果的なんだよね。
4. レスポンスの検証
取得したデータの検証を行う。
予期しないデータの拒否や、Content-Typeのチェックを行う。
$response = wp_safe_remote_get($url);
$content_type = wp_remote_retrieve_header($response, 'content-type');
if (strpos($content_type, 'application/json') === false) {
die('予期しないContent-Typeです');
}これも結構大事。っていうか、これをやっておくと、予期しないデータを取得しちゃった時に気づけるんだよね。
5. プラグインの更新
脆弱性が修正されたバージョンに更新する。
これは基本中の基本だよね。正直、これをやらないと話にならない。
6. WordPressコアの更新
最新バージョンに保つ。
これも基本。っていうか、WordPressコアの更新は自動化しておくのがおすすめ。
7. セキュリティプラグインの導入
Wordfenceなどでリクエストを監視する。
これも結構効果的。っていうか、僕もWordfenceを使ってる。リアルタイムで脅威を検出してくれるから、すごく便利なんだよね。
僕が実際にやった対策
僕が実際にやった対策を紹介するね。
あのクライアントサイトで、SSRF攻撃を受けた後、僕はこんな対策をした。
1. 脆弱なプラグインの削除
まず、脆弱性があったプラグインを削除した。で、代替のプラグインを探して、セキュリティがしっかりしてるやつに変更した。
2. ホワイトリストの実装
外部URLにアクセスする機能には、ホワイトリストを実装した。
これで「許可されたドメインだけにアクセスできる」ようにした。
3. ファイアウォールの設定
サーバーのファイアウォールを設定して、Webサーバーから内部ネットワークへのアクセスを制限した。
これで「内部ネットワークへのアクセスはブロックされる」ようにした。
4. Wordfenceの導入
Wordfenceを導入して、リアルタイムで脅威を監視するようにした。
これで「怪しいアクセスがあったらすぐに気づける」ようにした。
5. 定期的なセキュリティ監査
定期的にセキュリティ監査を行うようにした。
これで「新しい脆弱性が見つかったらすぐに対応できる」ようにした。
これらの対策をやってから、SSRF攻撃は受けてない。よし、これで安心だな、って思った。
よくある質問(FAQ)
Q1: SSRF攻撃とXSS攻撃の違いは?
SSRF攻撃は、サーバー側でリクエストを送信させる攻撃で、XSS攻撃は、クライアント側(ブラウザ)でスクリプトを実行させる攻撃だ。
SSRF攻撃は内部ネットワークへのアクセスが可能になるから、XSS攻撃よりも深刻な被害をもたらす可能性がある。
Q2: wp_safe_remote_get()を使っていれば安全?
いや、完全に安全じゃない。
wp_safe_remote_get()はwp_http_validate_url()に依存してて、この関数はDNS再バインディング攻撃に対して脆弱だ。
だから、ホワイトリスト方式や入力検証を追加で実装する必要がある。
Q3: SSRF攻撃を受けたかどうか確認する方法は?
サーバーログを確認して、内部ネットワークへのアクセスログがないかチェックする。
あと、Wordfenceなどのセキュリティプラグインを導入して、リアルタイムで監視するのもおすすめ。
Q4: SSRF攻撃を受けた場合の対処法は?
- 脆弱なプラグインを削除または更新
- ホワイトリストの実装
- ファイアウォールの設定
- セキュリティプラグインの導入
- 定期的なセキュリティ監査
これらの対策を順番にやっていけば、SSRF攻撃のリスクを大幅に減らせる。
Q5: プラグイン開発者として、SSRF脆弱性を防ぐには?
- ユーザー入力を直接
wp_safe_remote_get()に渡さない - ホワイトリスト方式を実装する
- 入力検証を徹底する
- レスポンスの検証を行う
- セキュリティ監査を定期的に実施する
これらを守れば、SSRF脆弱性を防げる。っていうか、プラグイン開発者はこれを絶対に守ってほしい。
まとめ
最後にまとめるね。
Point(結論の再強調):
SSRF攻撃は、サーバーを踏み台にして内部リソースにアクセスする攻撃手法で、WordPressでは「安全」と名付けられた関数でさえ完全には安全ではない。対策としては、ホワイトリスト方式、入力検証、ネットワーク分離が不可欠で、プラグインの更新とセキュリティプラグインの導入も重要だ。定期的なセキュリティ監査を行い、新しい脆弱性に常に注意を払うことが、サイトを守る鍵となる。
SSRF攻撃は、見た目にはわかりにくいけど、内部ネットワークへのアクセスやファイルシステムの読み取りなど、深刻な被害をもたらす可能性がある。
WordPress固有のSSRF脆弱性として、wp_http_validate_url()の問題がある。この関数はDNS再バインディング攻撃に対して脆弱で、wp_safe_remote_get()などの「安全」と名付けられた関数でさえ、完全には安全じゃない。
対策としては、ホワイトリスト方式の導入、入力検証の徹底、ネットワーク分離が重要だ。あと、プラグインの更新、WordPressコアの更新、セキュリティプラグインの導入も忘れずに。
僕が実際にやった対策も紹介したけど、これらを実践すれば、SSRF攻撃のリスクを大幅に減らせる。
正直、SSRF攻撃は怖いけど、適切な対策をすれば防げる。だから、この記事を読んで、ぜひ対策を実践してほしい。
みんなのWordPressサイトが安全でありますように。
WordPressのセキュリティ診断、してますか?

WordPressサイトのセキュリティ、最後にチェックしたのはいつですか?脆弱性は日々進化しています。定期的なセキュリティ診断で、あなたのサイトを守りましょう。
今すぐ無料診断を申し込む → https://example.com/security-check
プロのセキュリティエンジニアが、あなたのWordPressサイトを徹底的にチェック。脆弱性を発見し、具体的な対策をご提案します。