2026年9月22日
2026年9月22日
WordPressのログイン試行回数を制限する方法・ブルートフォース攻撃対策
はじめに
「WordPressのログインページに大量のアクセスがある」「見覚えのないIPからのログイン試行が多い」——ブルートフォース攻撃(パスワード総当たり攻撃)はWordPressへの最も一般的な攻撃手法のひとつです。ログイン試行回数を制限して防御しましょう。
症状・原因
WordPressはデフォルトでログイン試行回数に制限がないため、攻撃者は/wp-login.phpに対して自動化されたツールで何千回もパスワードを試し続けることができます。適切な制限設定がなければ、弱いパスワードのアカウントが乗っ取られるリスクがあります。
解決手順
ステップ1:現在のログイン失敗状況を確認する
# Nginxのアクセスログでwp-login.phpへのアクセスを確認
grep "POST /wp-login.php" /var/log/nginx/access.log \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# Apacheの場合
grep "POST.*wp-login.php" /var/log/apache2/access.log \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# WordPressのデバッグログを確認
wp eval '
$entries = file("/var/log/wordpress/debug.log");
$fails = array_filter($entries, fn($l) => strpos($l, "incorrect password") !== false);
echo count($fails) . " failed logins found\n";
'
ステップ2:Limit Login Attemptsプラグインを設定する
# Limit Login Attempts Reloadedをインストール
wp plugin install limit-login-attempts-reloaded --activate
# 設定を確認
wp option get limit_login_options
管理画面 → 設定 → Limit Login Attempts
→ ログイン失敗の許容回数: 3回
→ ロックアウト時間: 20分
→ 連続ロックアウト後の待機時間: 24時間
→ IPアドレスをログに記録: ON
→ メール通知: ON(4回ロックアウトごとに通知)
ステップ3:functions.phpで独自のログイン制限を実装する
// ログイン失敗回数をトランジェントで管理
add_filter( 'wp_authenticate_user', function( $user, $password ) {
if ( is_wp_error( $user ) ) return $user;
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'login_fails_' . md5( $ip );
$fails = (int) get_transient( $key );
$limit = 5; // 5回まで許可
if ( $fails >= $limit ) {
return new WP_Error(
'too_many_attempts',
'試行回数が多すぎます。20分後に再試行してください。'
);
}
return $user;
}, 10, 2 );
// ログイン失敗時にカウントアップ
add_action( 'wp_login_failed', function( $username ) {
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'login_fails_' . md5( $ip );
$n = (int) get_transient( $key ) + 1;
set_transient( $key, $n, 20 * MINUTE_IN_SECONDS ); // 20分間
} );
// ログイン成功時にリセット
add_action( 'wp_login', function() {
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'login_fails_' . md5( $ip );
delete_transient( $key );
} );
ステップ4:NginxでIPレベルの制限を設定する
# /etc/nginx/conf.d/wp-login-limit.conf
limit_req_zone $binary_remote_addr zone=wp_login:10m rate=1r/s;
server {
# ...
location = /wp-login.php {
limit_req zone=wp_login burst=3 nodelay;
limit_req_status 429;
# 特定IPのみ許可する場合
# allow 203.0.113.1; # 自社IPを許可
# deny all;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
# Nginx設定を再読み込み
sudo nginx -t && sudo systemctl reload nginx
ステップ5:攻撃IPをfail2banで自動ブロックする
# fail2banのWordPress用フィルターを作成
sudo cat > /etc/fail2ban/filter.d/wordpress.conf << 'EOF'
[Definition]
failregex = ^<HOST> .* "POST .*wp-login.php
ignoreregex =
EOF
# jail設定に追加
sudo cat >> /etc/fail2ban/jail.local << 'EOF'
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600
findtime = 600
EOF
sudo systemctl restart fail2ban
# ブロック中のIPを確認
sudo fail2ban-client status wordpress
注意事項
- ロックアウト設定が厳しすぎると、自分自身がログインできなくなる場合があります。管理者IPを許可リストに追加しておくことを推奨します。
- CloudflareなどのCDNを経由している場合、
$_SERVER['REMOTE_ADDR']には実際の攻撃者IPではなくCDNのIPが入ります。HTTP_CF_CONNECTING_IPなどのヘッダーを使用してください。 - ログイン試行制限と同時に、強力なパスワードポリシーと二要素認証(2FA)の導入も強くお勧めします。
まとめ
ログイン試行制限は「現状確認→プラグイン設定→独自実装→Nginx制限→fail2ban自動ブロック」の多層防御で実装します。WP-CLIで定期的にログを確認し、新しい攻撃パターンに対応しましょう。関連記事:WordPressのログインURLを変更する方法、WordPressのXMLRPCを無効化する方法。