WPセキュリティ:wp-adminのセキュリティ|ログインURL変更・ログイン試行制限・XML-RPC

wp-adminのセキュリティは、WordPressの管理画面とログイン画面から入ってくる総当たり攻撃を防ぐ設定です。WordPressサイトを複数運営しているNginx + Apache構成のサーバーのアクセスログを確認したところ、ログインURLを変えた後もxmlrpc.phpへの自動リクエストが続いていたため、サーバー側の速度制限まで合わせて適用しました。
1️⃣ wp-adminとwp-login.phpが狙われる理由
WordPressの管理画面のURLが知られていることは弱点ですが、セキュリティを強化して補えます。すべてのWordPressサイトが同じ/wp-admin/と[wp-login.php]を使い、ログアウトした状態で/wp-admin/を開くと[wp-login.php]のログイン画面へ移動します。
攻撃は、このログイン画面にユーザー名とパスワードを繰り返し入れてみる総当たりで入ってきます。そのためwp-adminのセキュリティは、URLを隠すことよりログイン試行を止めることが先です。
2️⃣ ログインURL変更の効果と限界
セキュリティプラグインでログインURLを変えると、既定の[wp-login.php]は404を返すようになり、既定のURLをそのまま叩く自動攻撃はログイン画面までたどり着けません。変えたURLは管理者アカウントを持つ人に別途伝える必要があります。
この方法は手間が少ないですが、変えたURLを忘れると管理画面に入れず、FTPやファイルマネージャーでそのプラグインのフォルダー名を変えて無効化する必要があります。複数人で管理するサイトなら、アドレスを1か所に記録しておくのが適切です。
3️⃣ ログイン試行制限と2段階認証
ログインURLを変えても、新しいアドレスが知られればパスワードを当てる試みはそのまま続きます。WordPressのコアにはログイン失敗回数の制限がなく、間違ったパスワードを何度入れても同じログイン画面がまた開きます。
ログイン試行制限プラグインは決められた回数を超えたIPを一定時間ブロックし、2段階認証はパスワードが正しくてもスマートフォンの認証アプリのコードをもう一度求めます。2段階認証をオンにするときは、スマートフォンをなくしたときに使うバックアップコードも一緒に保管します。
4️⃣ xmlrpc.phpを閉じる
[xmlrpc.php]はログイン画面を通らずにユーザー名とパスワードを受け取る2つ目の入口で、[system.multicall]方式を使うと1回のリクエストで複数のパスワードを試せます。
WordPressサイトを複数運営しているNginx + Apache構成のサーバーのアクセスログを見ると、10月13日0時から9時50分までに[xmlrpc.php]へのPOSTリクエストが2,250件ありました。リクエストは22個のIPから届き、User-AgentはJetpackとWordPress.comを装っていました。
WordPressのモバイルアプリやJetpackを使っていないなら、Nginxの設定で[xmlrpc.php]へのリクエストをブロックするか、セキュリティプラグインのXML-RPCオフ設定を使います。
# serverブロック内 — xmlrpc.phpへのリクエストを拒否
location = /xmlrpc.php {
deny all;
}この設定を入れると、[xmlrpc.php]へのGETとPOSTリクエストはPHPまで行かずにすべて403で終わります。セキュリティプラグインのXML-RPCオフはログインが必要なリクエストだけを拒否し、ファイルは応答し続けるため、PHPの実行まで減らすならNginxでブロックするのが適切です。
5️⃣ サーバーでブロック:管理者アクセスのIP制限・速度制限
固定IPからだけ管理するなら、Nginxで[wp-login.php]と/wp-admin/をそのIPだけに許可する方法がいちばん確実です。自宅や事務所のIPがよく変わる環境には向きません。
/wp-admin/全体をブロックすればよさそうですが、訪問者向けの検索やカートのような機能が[admin-ajax.php]へリクエストを送ることが多いため、そのファイルは開けておく必要があります。
# serverブロック内 — PHP処理のlocationより上に
location = /wp-login.php {
allow 203.0.113.10; # 管理に使う固定IP
deny all;
# この下にPHP処理locationの設定をそのまま移す
}指定したIP以外から[wp-login.php]を開くと403が出て、指定したIPではログイン画面が開きます。location内にはサイトのPHP処理設定(fastcgi_passなど)をそのまま移さないと、ログイン画面が正常に動きません。
IPを固定できないなら、ログインしていない訪問者のPHPリクエストに速度制限をかける方法があり、1分に30回に制限して自動リクエストがサーバー資源を占有できないようにした過程は php-fpm max_children 警告 の記事にあります。
# httpブロック — ログインCookieのないリクエストだけをIPごとに数える
map $http_cookie $php_anon_key {
default $binary_remote_addr;
"~*wordpress_logged_in" "";
}
limit_req_zone $php_anon_key zone=php_anon:10m rate=30r/m;
# PHP処理のlocation内
limit_req zone=php_anon burst=60 nodelay;
limit_req_status 429;ログインしていないIP 1つがPHPリクエストを続けて送ると、61回目までは処理され、その後は429が返され、ログインCookieのあるリクエストは数えません。ページキャッシュがPHPを通らずに応答する構成なら、一般の訪問者のページ閲覧はこの制限にかかりません。
ℹ️ 提携について
当サイトのコンテンツにはアフィリエイトリンクが含まれています。訪問者がこのリンクを通じて商品やサービスを購入すると、当サイトは販売元から手数料を受け取ります。この過程において、購入者が支払う金額(イベント割引適用で金額が下がります↓)は上昇しません。掲載されている価格・割引・在庫情報は作成時点のものであり、実際とは異なる場合がありますので、ご購入前に販売元にて最終確認をお願いいたします。商品の選定および評価は独自の基準に基づいて行われており、手数料の支払いの有無は紹介順や評価内容に影響を与えません。