WordPress XML-RPC:無効化する方法3つ&xmlrpc.php攻撃の見分け方|Jetpackの例外

公正取引委員会の広告文 Ver 3.1
公正取引委員会の広告文 Ver 3.2(モバイル専用)

WordPressサイトのアクセスログに、同じIPからxmlrpc.phpへのリクエストが数百件続いているなら、WordPress XML-RPCを狙ったパスワード総当たりです。WordPressサイトを複数運営しているNginx + Apache構成サーバーの1日分のアクセスログ8,624件を分類し、無効化する方法3つを実際に適用してレスポンスコードを確認した結果、どの層でブロックすればPHPの実行まで減るのかを整理しました。

XML-RPCは、HTTPでXML文書をやり取りしてWordPressの機能をリモートで呼び出す規約で、WordPress 3.5からは設定画面のオン・オフ項目がなくなり、インストール直後からオンの状態で動いています。

1️⃣ xmlrpc.phpの役割と使われる場面

REST APIができてからは[xmlrpc.php]をもう使われないファイルと思いがちですが、Jetpackは今もこのファイルを通してWordPress.comとサイトをつないでいます。Jetpackの公式ドキュメントはXML-RPC接続に依存すると明記しており、XML-RPCを標準でブロックするホスティングではJetpackの接続自体が失敗します。今でも事務所にFAX番号を1つ残しておくのと同じです。

WordPress 7.1時点でこのファイルが受け付けるメソッドは77個で、記事・メディア・コメントを扱うwp系50個、古いブログ規約(MetaWeblog、MovableType、Blogger)23個、ピンバック2個、テスト用のdemo 2個で構成されています。

wp系はリクエスト本文に含まれるユーザー名とパスワードでログインするため、ログイン画面を通りません。記事の作成と編集、メディアのアップロード、コメント管理はすべてこの系統で、古いブログ規約23個は、他のブログツールと同じ方式で記事をやり取りするために残されているメソッドです。

demo.sayHelloは、WordPress XML-RPCに入っているテスト呼び出しです。送ると[Hello!]の一言だけを返し、ログインが不要なので、XML-RPCが動いているかを確認する用途で使います。対になるものとして、2つの数を足して返すdemo.addTwoNumbersがあります。

いずれもPOSTでXML本文を送らないと応答せず、ブラウザーでアドレスを開くと[XML-RPC server accepts POST requests only.]という文言とともに405が返ります。

ピンバックもこのファイルの担当です。記事を公開すると、本文でリンクしたサイトのxmlrpc.phpにピンバックを送り、受け取った側のサーバーは送信元のアドレスを直接開いてリンクが本当にあるかを確認します。

🧭 xmlrpc.phpに届くリクエストと処理
wp-adminのセキュリティ解説ダイアグラム
📨 送信側
↓
入口
xmlrpc.php
POSTで送られたXML本文だけを処理
405 · XML-RPC server accepts POST requests only.
メソッド77個
wp.*記事・メディア・コメント 50個
metaWeblog · mt · blogger古いブログ規約 23個
pingback.*ピンバック 2個
demo.*動作確認用のテスト呼び出し 2個
結果
WordPress.comとの接続を維持
リクエスト本文のユーザー名・パスワードを確認 → 記事の作成・編集
送信元のアドレスをサーバーが直接開いてリンクを確認
ログインなしで Hello! 応答
処理なし
JetpackはWordPress.comとの接続をこのファイルで維持しているため、ファイルをブロックすると接続が切れます。
外部の投稿ツールはリクエスト本文に入れたユーザー名とパスワードでログインし、ログイン画面を通りません。
記事でリンクしたサイトのxmlrpc.phpにピンバックを送り、受け取った側のサーバーは送信元のアドレスを直接開いてリンクを確認します。
demo.sayHelloはXML-RPCが動いているかを確認するテスト呼び出しで、ログインなしで[Hello!]の一言で応答します。
ブラウザーでアドレスを開くと、[XML-RPC server accepts POST requests only.]という文言とともに405が返ります。

2️⃣ アクセスログで見るxmlrpc.php攻撃

パスワード総当たりはログイン画面を通らず、[xmlrpc.php]から入ってきます。WordPressサイトを複数運営しているNginx + Apache構成サーバーの10月14日0時から20時までのアクセスログでは、POST /xmlrpc.phpリクエストは8,624件、IPは72個で、そのうち19個のIPがちょうど300件ずつ送っていました。

あるIPは14時9分から37分までの28分間に300件を送り、5〜6秒の間隔が最後まで一定でした。8,524件のリクエストはUser-AgentにJetpackまたはWordPress.comを名乗って入ってきており、[Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)]のように実際のJetpackの形式をまねた値を、同じIPが複数使い分けていました。

同じ日の14時までは、セキュリティプラグインのXML-RPCオフがこのリクエストをホームへ302で戻しており、14時以降にNginxでブロックしてからは403で終わりました。302は本文が0バイトでもリクエストごとにPHPが実行された結果で、403はPHPを通らなかった応答です。

🧭 アクセスログ1行で見るxmlrpc.php攻撃
解説ダイアグラム
🛡️ サーバーの状態
アクセスログ1行(Nginx access.log)
203.0.113.25IP[14/Oct/2026:14:09:04 +0900]時刻"POST /xmlrpc.php HTTP/1.1"リクエスト302403状態0153バイト"Jetpack by WordPress.com (Jetpack 13.0; WordPress 6.3)"User-Agent
PHP実行・ホームへ302PHPを通らない・Nginx標準の403ページ
セキュリティプラグインでXML-RPCをオフにした状態では、リクエストをホームへ戻す302が記録されます。本文は0バイトですが、その302を返すためにPHPが実行されます。
Nginxでブロックすると、403と標準エラーページの153バイトが記録され、PHPは実行されません。
同じIPからのリクエスト
14:09:0414:37:20
28分間に300件、5〜6秒間隔
0時〜20時 POST 8,624件IP 72個300件ずつ送ったIP 19個Jetpack・WordPress.comを偽るUA 8,524件

3️⃣ system.multicallとパスワード総当たり

[system.multicall]で1回のリクエストに数百個のパスワードを試せるという説明が多いですが、WordPressは1つのリクエスト内でログインが一度失敗すると、残りの呼び出しのパスワードを照合しません。最初の呼び出しだけがwp_authenticateを通り、以降の呼び出しは検査なしで同じエラー[Incorrect username or password.]を返します。

呼び出しの数だけ応答はそのまま返るため、間違ったパスワード100個を入れたリクエスト1つに対し、23KBの応答でエラー100個が0.12秒で返ります。同じリクエスト内で正しいパスワードを後ろに置くと前の呼び出しの失敗のために一緒に拒否され、前に置くとその呼び出しだけ成功します。パスワードの照合は1回ですが、XMLの解析とWordPressの読み込みはリクエストごとに繰り返されるため、この攻撃のサーバー負荷はログイン検査ではなくリクエスト数そのものから生じます。

4️⃣ XML-RPCを無効化する方法3つとレスポンスコード

プラグインでXML-RPCをオフにしても、[xmlrpc.php]へのリクエストはPHPまで届きます。フィルターでオフにした状態で呼び出し100個のリクエストを送っても、HTTP 200でエラー100個(24KB)がそのまま返ってきました。どの層で拒否するかによって方法は3つに分かれ、レスポンスコードもそれぞれ異なります。

1. コードでxmlrpc_enabledフィルターをオフにする

テーマのfunctions.phpに、[xmlrpc_enabled]フィルターをfalseにするadd_filterを1行入れれば済みます。この状態では、ログインが必要な呼び出しは[XML-RPC services are disabled on this site.]というエラーとHTTP 405で拒否されますが、ログインの要らないテスト呼び出しdemo.sayHelloは引き続き200で応答します。

2. プラグイン設定でオフにする:Perfmatters・Hide My WP

PerfmattersやHide My WPなどのプラグインで、Disable XML-RPC設定を使って無効化する方法です。Hide My WPは上と同じフィルター方式なので応答も同じですが、Perfmattersは同じフィルターに加えて[xmlrpc.php]への直接リクエストを403で終わらせ、ピンバックのヘッダーとピンバックリンクまで取り除くため、オフにするとGETもPOSTも403で応答します。ただし403を返すためにWordPressがinit段階まで実行されるので、応答まで0.13〜0.15秒と開いているときと同じ時間がかかり、PHPの負荷は残ります。

🔌 プラグイン設定でXML-RPCをオフにする
📍 Settings › Perfmatters › General › Core › Disable XML-RPC
トグルをオンにして[Save Changes]を押すと、下の訪問者の画面が変わります。
管理画面
Settings saved.
perfmatters
⚙ GeneralVersion 2.6.8
Core
Disable Emojis?
Disable Dashicons?
Disable Embeds?
Disable XML-RPC?
Remove RSD Link?
Remove jQuery Migrate?
Hide WP Version?
Remove Shortlink?
Disable RSS Feeds?
Remove RSS Feed Links?
Disable Self Pingbacks?
Disable REST API?
Remove REST API Links?
Disable Google Maps?
Disable Password Meter?
Disable Comments?
Remove Comment URLs?
Add Blank Favicon?
Remove Global Styles?
Block Style Behavior?
Disable Heartbeat?
Heartbeat Frequency?
Limit Post Revisions?
Autosave Interval?
Login URL
Custom Login URL?
Disabled Behavior?
Message?
📍 Hide My WP › Settings › Cleanup › Disable XML RPC
チェックして[Save Settings]を押すと、下の訪問者の画面が変わります。
管理画面
Hide My WP
Settings was updated successfully!
Cleanup
Minify HTML
Remove comments and whitespaces from HTML (Use with cache).
Minify style
Remove theme info and other comments from stylesheet. (Require new style name)(Use with cache!).
Replace \/ URLs
Choose if you see Javascript URLs (e.g. \/wp-content\/themes)
Feed Meta
Other Meta
Default Tagline
Remove Version
Body Classes
Menu Classes
Post Classes
Clean up other
Replace in AJAX
Change Nonce
Disable XML RPC
Internal CSS
Useful to paste internal CSS code (Require New Theme Path)
Internal JS
Useful to paste internal JS code (Require New Theme Path)
ログアウト中の訪問者の画面 — 保存した設定でリクエスト
405
XML-RPC server accepts POST requests only.
GETリクエストはどの設定でも405です。
200
Hello!
動作確認用のテスト呼び出しなので、ログインなしで応答します。
200
faultCode 403 · Incorrect username or password.
パスワードの照合が実行されます。ログインURLを変えても同じです。
403
本文なし
Perfmattersがinit段階で403で終わらせます。PHPは実行されます。
403
本文なし
Perfmattersがinit段階で403で終わらせます。PHPは実行されます。
403
本文なし
パスワードの照合なしで403で終わります。PHPは実行されます。
200
Hello!
フィルター方式なので、ログインの要らない呼び出しはそのまま応答します。
405
faultCode 405 · XML-RPC services are disabled on this site.
ログインが必要な呼び出しだけが拒否されます。

3. Webサーバーでブロック:Nginx・Apache

NginxでもApacheでもPHPの手前でリクエストを拒否するため、プラグイン方式と違ってWordPressは実行されません。

# Nginx — serverブロック内、PHP処理のlocationより上に
location = /xmlrpc.php {
    deny all;
}

このlocationブロックはPHP処理のlocationより上に置き、[xmlrpc.php]に完全一致するリクエストをNginxがその場で拒否します。入れた後は設定を点検して再読み込みしないと反映されません。

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
systemctl reload nginx

再読み込み後はGETもPOSTもPHPまで行かずに403で終わり、応答本文はNginx標準の403ページ153バイトで、応答まで0.02秒です。

# Apache — サイトルートの.htaccess(Apache 2.4)
<Files xmlrpc.php>
    Require all denied
</Files>

Apacheだけを使うサーバーでは、サイトルートの.htaccessに上のFilesディレクティブを入れればすぐに適用され、Apache標準の403ページ(199バイト)が同じ0.02秒で返ります。

curl -s -o /dev/null -w '%{http_code}' -X POST https://example.com/xmlrpc.php -d '<methodCall><methodName>demo.sayHello</methodName></methodCall>'
403

上のコマンドはテスト呼び出しdemo.sayHelloをPOSTで送ってレスポンスコードを確認するもので、Webサーバーでブロックした後は403が返ります。[-o /dev/null]と[-w]のオプションを外して送ると本文が見え、[Hello!]が返れば開いている状態ですが、フィルターだけでオフにしたサイトも同じ応答なので、ログイン呼び出しまで送らないと405は確認できません。

5️⃣ オフにしてはいけない場合と代替策

Webサーバーで丸ごとブロックする方法は効果が最も大きいですが、JetpackでWordPress.comと接続しているサイトには向きません。JetpackはXML-RPC接続に依存しており、WP EngineのようにXML-RPCを標準でブロックするホスティングでは、Jetpack側の案内に従って例外を開けないと接続できません。ピンバックを受け取りたいサイトも同様です。

こうしたサイトでは、Jetpackが公開しているIPリスト(jetpack.com/ips-v4.txt)だけを許可して残りを拒否する形に絞ります。Nginxのlocationブロック内にIP帯の数だけallow行を入れ、最後にdeny allを置けば済みます。

完全にブロックできないなら、ログインしていないリクエストに1分あたりの回数制限をかける方法が残ります。設定は wp-adminのセキュリティ の記事のNginx速度制限の項目と同じで、ログインCookieのないリクエストだけを数えるため、ログインした管理者の作業には影響しません。

🔢 FAQ & おすすめコンテンツ

削除しても、WordPressコアを更新するとパッケージに入っているファイルがそのまま再びコピーされるため、次の更新時に復元されます。ファイルを削除する代わりに、Webサーバーでそのアドレスをブロックするかフィルターで無効化するほうが、更新後も維持されます。

REST APIは[wp-json]アドレスから入る別の入口なので、XML-RPCを無効化してもそのまま開いています。ブロックエディターがこの入口を使うため、完全に無効化せず、ログアウト状態のリクエストだけをブロックする方法が適切です。

確認せずに送ります。WordPressはどのサイトでも同じパスにこのファイルがあるため、スキャナーはアドレスだけを変えながらPOSTを送ります。初期状態のWordPressは、ページのheadにある[EditURI]リンクと、ピンバックを受け付ける記事の[X-Pingback]ヘッダーで、xmlrpc.phpのアドレスを自ら公開しています。

🛡️ WordPressセキュリティのおすすめコンテンツ 記事8・外部2
🗂️ WordPressセキュリティ
📋 wp-adminのセキュリティ 📄 総当たり対策9つ 📄 Hide My WP 📄 セキュリティプラグイン ベスト5
📄 XML-RPCの無効化 📄 REST API 📄 ピンバック・トラックバック 📄 wp-config.phpのセキュリティ
📡 Nanaco Japan xmlrpc.php攻撃の対処法 📡 サイトの主治医 xmlrpc.php無効化・確認
検索結果がありません。

ℹ️ 提携について
当サイトのコンテンツにはアフィリエイトリンクが含まれています。訪問者がこのリンクを通じて商品やサービスを購入すると、当サイトは販売元から手数料を受け取ります。この過程において、購入者が支払う金額(イベント割引適用で金額が下がります↓)は上昇しません。掲載されている価格・割引・在庫情報は作成時点のものであり、実際とは異なる場合がありますので、ご購入前に販売元にて最終確認をお願いいたします。商品の選定および評価は独自の基準に基づいて行われており、手数料の支払いの有無は紹介順や評価内容に影響を与えません。