2026年5月20日
2026年5月20日
WordPressのセキュリティ対策の基本
はじめに
WordPressはCMSシェア40%超のため攻撃者の標的になりやすいプラットフォームです。基本的なセキュリティ対策を施すだけで不正アクセスリスクを大幅に低減できます。本記事では追加プラグインなしで実装できる基本的なセキュリティ設定を解説します。
症状・原因
- 管理画面への不正ログイン試行が多い(ログにwarningが大量出力)
- WordPressのバージョン情報が外部から確認できる状態になっている
- XML-RPCへのブルートフォース攻撃を受けている
- wp-config.phpのセキュリティキーが初期値のまま
解決手順
ステップ1:wp-config.phpを強化する
// wp-config.php
// セキュリティキーを更新(https://api.wordpress.org/secret-key/1.1/salt/ で生成)
define('AUTH_KEY', 'ランダムな文字列をここに');
define('SECURE_AUTH_KEY', 'ランダムな文字列をここに');
define('LOGGED_IN_KEY', 'ランダムな文字列をここに');
define('NONCE_KEY', 'ランダムな文字列をここに');
define('AUTH_SALT', 'ランダムな文字列をここに');
define('SECURE_AUTH_SALT', 'ランダムな文字列をここに');
define('LOGGED_IN_SALT', 'ランダムな文字列をここに');
define('NONCE_SALT', 'ランダムな文字列をここに');
// 管理画面からのファイル直接編集を無効化
define('DISALLOW_FILE_EDIT', true);
// プラグイン・テーマのインストールを無効化(本番環境向け)
define('DISALLOW_FILE_MODS', true);
// デバッグ情報を非表示(本番環境)
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', true); // ログはファイルに記録
// データベーステーブルプレフィックスを変更(インストール時に設定)
$table_prefix = 'wp_xxxxxx_'; // デフォルトの wp_ から変更
ステップ2:XML-RPCを無効化する
// functions.php
// XML-RPC を完全に無効化
add_filter('xmlrpc_enabled', '__return_false');
// XML-RPC のピングバックを無効化
add_filter('xmlrpc_methods', function (array $methods): array {
unset($methods['pingback.ping']);
unset($methods['pingback.extensions.getPingbacks']);
return $methods;
});
# .htaccess: XML-RPC へのアクセスをブロック(Apacheの場合)
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>
# nginx.conf: XML-RPC へのアクセスをブロック
location = /xmlrpc.php {
deny all;
return 403;
}
ステップ3:WordPress バージョン情報を隠す
// functions.php
// バージョン情報を削除
remove_action('wp_head', 'wp_generator');
// RSSフィードからもバージョンを削除
add_filter('the_generator', '__return_empty_string');
// スタイルシート・スクリプトのバージョンクエリを削除
add_filter('style_loader_src', function (string $src): string {
return remove_query_arg('ver', $src);
});
add_filter('script_loader_src', function (string $src): string {
return remove_query_arg('ver', $src);
});
ステップ4:REST APIのアクセスを制限する
// functions.php
// 未ログインユーザーからのREST APIアクセスを制限
add_filter('rest_authentication_errors', function (mixed $result): mixed {
// すでに認証エラーがある場合はそのまま返す
if (!empty($result)) {
return $result;
}
// ログインしていない場合はエラーを返す
if (!is_user_logged_in()) {
return new WP_Error(
'rest_not_logged_in',
__('REST APIはログインユーザーのみ利用可能です。', 'mytheme'),
['status' => 401]
);
}
return $result;
});
// 特定のエンドポイントのみ公開する場合(上の制限と排他的)
add_filter('rest_endpoints', function (array $endpoints): array {
// ユーザー一覧エンドポイントを削除(ユーザー名漏洩防止)
if (isset($endpoints['/wp/v2/users'])) {
unset($endpoints['/wp/v2/users']);
}
if (isset($endpoints['/wp/v2/users/(?P<id>[\d]+)'])) {
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
ステップ5:管理者アカウントを保護する
// functions.php
// 「admin」ユーザー名でのログインを拒否
add_action('wp_authenticate', function (string $username): void {
if (strtolower($username) === 'admin') {
// ユーザー名として admin を使用している場合は強制ログアウト
wp_die(
'セキュリティ上の理由から "admin" ユーザー名でのログインは禁止されています。',
'ログインエラー',
['response' => 403, 'back_link' => true]
);
}
});
// ログイン失敗時のエラーメッセージを汎用化(ユーザー名の存在確認を防ぐ)
add_filter('login_errors', function (): string {
return 'ユーザー名またはパスワードが正しくありません。';
});
// ログイン試行回数を制限(簡易版)
add_filter('authenticate', function (mixed $user, string $username): mixed {
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
$transient = 'login_attempts_' . md5($ip);
$attempts = (int) get_transient($transient);
$max_attempts = 5;
if ($attempts >= $max_attempts) {
return new WP_Error('too_many_attempts', 'ログイン試行回数が上限に達しました。15分後に再試行してください。');
}
if (is_wp_error($user)) {
set_transient($transient, $attempts + 1, 15 * MINUTE_IN_SECONDS);
}
return $user;
}, 30, 2);
注意事項
DISALLOW_FILE_MODSを有効にするとプラグイン・テーマの自動更新も無効になります。本番環境では手動でのアップデート運用が必要です- セキュリティキーを変更すると、すべてのログインセッションが無効になります。編集前に管理者が確実にログインできる状態を確認してください
- REST APIを完全に無効にするとブロックエディタ(Gutenberg)が動作しなくなります。エンドポイント単位で制限することを推奨します
まとめ
wp-config.php でセキュリティキーの更新・ファイル編集の無効化・デバッグ非表示を設定します。xmlrpc_enabled フィルターでXML-RPCを無効化し、.htaccessでもアクセスをブロックします。バージョン情報は wp_generator の削除とクエリパラメータの除去で隠します。REST APIはユーザー一覧エンドポイントを削除してユーザー名漏洩を防ぎます。