WordPressサイトのアクセスログを見ると、/wp-login.php や /xmlrpc.php への見覚えのないアクセスが毎日大量に記録されている——これはほぼ全サイト共通の状態です。WordPress は標準ではログイン試行回数に制限がなく、放置すると総当たり(ブルートフォース)やリスト型攻撃でいつか管理者アカウントを突破されかねません。
この記事は Web 担当者・サイト運営者・制作会社向けに、WordPress のログイン周りを「今日サーバ設定だけで固める」ための 5 つの対策を、nginx / Apache / PHP のコピペ設定つきでまとめたものです。難しいプラグインを増やさず、サーバ側で攻撃の入口を絞るのが狙いです。
用語補足:総当たり攻撃=パスワードを片っ端から試す攻撃。リスト型攻撃=どこかで漏れた ID/パスワードの組をそのまま試す攻撃。WordPress では両方が
wp-login.phpとxmlrpc.phpに集中します。
各設定を入れる前に、必ず現在の設定ファイルをバックアップし、SSH など別経路でサーバに入れる状態を確保してから作業してください。ログイン経路を絞る作業なので、設定ミスで自分が締め出されるのが一番の事故です。
対策1: ログイン試行回数を制限する(ロックアウト)
最優先はこれです。標準の WordPress は何回パスワードを間違えてもロックしません。失敗が一定回数を超えたら、その IP を一時的にブロックします。
サーバ設定に触れない運用なら、Limit Login Attempts Reloaded のような実績あるプラグインが手軽です。推奨設定の目安は次のとおりです。
- 失敗許容回数: 3〜4 回
- ロックアウト時間: 20 分(繰り返す IP は数時間に延長)
- ロックアウトのメール通知: ON(攻撃の兆候に気づける)
プラグインを増やしたくない場合は、後述の 対策4(レート制限) をサーバ側で入れれば、同等の「速度を奪う」効果が得られます。アプリ層(PHP)のロックアウトは攻撃が激しいとサーバ資源を消費するため、可能ならサーバ/エッジ側の制限を併用するのが堅実です。
対策2: xmlrpc.php を無効化する
xmlrpc.php は古いリモート投稿用のエンドポイントで、現代のほとんどのサイトでは不要です。やっかいなのは、system.multicall を使うと 1 リクエストで数百個のパスワードをまとめて試せる点で、wp-login.php 側のロックアウトをすり抜けて総当たりされる温床になります。Jetpack や WordPress 公式モバイルアプリを使っていなければ、無効化して問題ありません。
まず PHP 側(テーマの functions.php)で機能そのものを止めます。
// xmlrpc 機能を無効化(子テーマの functions.php に追記)
add_filter( 'xmlrpc_enabled', '__return_false' );
さらに サーバ側でファイルごと遮断しておくと、PHP を起動する前にはじけて軽量です。
nginx:
# server {} ブロック内
location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
return 403;
}
Apache(.htaccess でも可):
<Files "xmlrpc.php">
Require all denied
</Files>
Jetpack 等で xmlrpc が必要な場合は
deny allの代わりに、利用元の IP だけallowする形にしてください。完全に塞ぐと連携が切れます。
対策3: wp-login.php へのアクセスをIP/BASIC認証で限定する
管理者のログイン元が固定 IP(自社オフィスや VPN)なら、そもそも他からは wp-login.php を開けないようにするのが最強です。
Apache(.htaccess)で固定 IP のみ許可:
<Files "wp-login.php">
Require ip 203.0.113.10
Require ip 198.51.100.0/24
</Files>
固定 IP が取れない在宅・出張環境では、nginx の BASIC 認証で「WordPress のログイン画面の手前にもう 1 枚扉」を足します。まず認証ファイルを作成します。
# office ユーザーのパスワードを対話入力で設定
sudo htpasswd -c /etc/nginx/.htpasswd-wp office
nginx 側の設定:
# server {} ブロック内
location = /wp-login.php {
auth_basic "Restricted login";
auth_basic_user_file /etc/nginx/.htpasswd-wp;
# 既存の PHP 処理へフォワード(環境に合わせてソケットを調整)
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
これでボットが wp-login.php を叩いても、WordPress のログイン処理に到達する前に 401 で弾かれます。設定反映前に sudo nginx -t で構文確認するのを忘れずに。
対策4: レート制限でボットの速度を奪う
固定 IP もプラグインも使えないケースの定番が、nginx の limit_req によるレート制限です。これは WordPress 公式ドキュメントでも推奨されている方法で、1 IP あたりのログイン試行を「1 分に数回」まで物理的に絞ります。
# http {} ブロックに定義(ゾーンの確保)
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=10r/m;
# server {} 内。対策3の auth_basic と同じ location にまとめてもよい
location = /wp-login.php {
limit_req zone=wplogin burst=3 nodelay;
include fastcgi_params;
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
rate=10r/m は 1 分間に 10 リクエストまで、burst=3 は瞬間的な超過を 3 件まで許容する設定です。正規ユーザーは数回打てれば十分なので、通常運用には影響しません。xmlrpc.php にも残すなら、同じゾーンを適用しておくと取りこぼしが減ります。
Apache 単体でレート制限したい場合は
mod_evasiveなどのモジュールが必要です。ただし設定が複雑になりやすいため、Apache 環境では対策1(ロックアウト)+ 対策3(IP/BASIC 制限)の組み合わせを優先するのが現実的です。
対策5: 二要素認証(2FA)を必須にする
パスワードが漏れても、もう 1 要素がなければログインできない——これが最後の砦です。Editor / Administrator 権限のアカウントには 2FA を必須にしましょう。
WordPress.org 公式の Two-Factor プラグインなどで、認証アプリ(Google Authenticator / Authy 等)による TOTP(時刻ベースのワンタイムコード) を有効化するのが基本です。SMS やメールよりも、認証アプリやハードウェアキー(YubiKey 等)のほうが安全性は高くなります。
2FA は「破られにくさ」を一段引き上げますが、レート制限やロックアウト(対策1・4)と組み合わせて初めて効果が出ます。2FA だけに頼ると、攻撃トラフィック自体は流れ続けるため、入口を絞る対策と必ずセットで導入してください。
番外: 自分が締め出されたときのリカバリ手順
ログイン経路を絞る設定では、自分がロックされる事故が一番起きがちです。慌てないように手順を用意しておきます。
-
IP/BASIC 制限で締め出された: SSH / コントロールパネルから該当の
.htaccessや nginx 設定をコメントアウト → 反映。 -
xmlrpc やレート制限を戻したい: 該当 location /
<Files>を一時的に外し、sudo nginx -t→sudo systemctl reload nginx。 - 2FA の端末を紛失した: SSH で WP-CLI を使い、対象ユーザーの 2FA 設定を無効化する。
# WP-CLI で Two-Factor の設定を消し、2FA を一時的に外す(復旧用)
wp user meta delete <ユーザーID> _two_factor_enabled_providers
復旧できたら、必ず原因を直して制限をもう一度かけ直すのを忘れないでください。
まとめ
WordPress のログイン総当たり対策は、1 つの銀の弾丸ではなく層で守るのが基本です。
- ログイン試行回数を制限(ロックアウト)
-
xmlrpc.phpを無効化(multicall総当たりを封じる) -
wp-login.phpを IP / BASIC 認証で限定 - レート制限でボットの速度を奪う
- 2FA を Editor / Administrator に必須化
固定 IP がある現場は「対策3 + 対策5」、不特定多数が編集する現場は「対策1 + 対策4 + 対策5」を軸にすると、運用を壊さず堅くできます。
関連記事
本記事の設定が正しく効いているかは、サイトドック(無料・登録不要)で自動チェックできます → https://sitedock.jp
お知らせ — バーチャルセキュリティコンシェルジュ「一ノ瀬あかり」がデビューしました🎉
JIISセキュリティラボから、セキュリティ用語をやさしく動画で解説する案内役「一ノ瀬あかり」が登場しました。よければデビューのご挨拶もご覧ください。