2026年7月28日

2026年7月28日

WordPressの不正ログインを防ぐ方法

はじめに

「WordPressのログインページに大量のアクセスがある」「管理者アカウントへのブルートフォース攻撃を防ぎたい」「xmlrpc.phpへの攻撃を止めたい」——ログインセキュリティの強化はWordPressサイト運営の最優先事項の一つです。

症状・原因

WordPressのデフォルトログインURL(/wp-login.php)は全世界に公開されており、ボットによるブルートフォース攻撃の標的になります。試行回数制限やログインURLの変更・二段階認証を組み合わせることで不正ログインリスクを大幅に低減できます。

解決手順

ステップ1:ログイン試行回数を制限する

// functions.php: ログイン失敗回数を制限する(プラグインなし)
// ※ Limit Login Attempts Reloadedプラグインを使う方が管理しやすい

// ログイン失敗時にIPと失敗回数をトランジェントに記録
add_action( 'wp_login_failed', function( $username ) {
    $ip       = sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '' );
    $key      = 'login_fail_' . md5( $ip );
    $failures = (int) get_transient( $key );

    set_transient( $key, $failures + 1, 15 * MINUTE_IN_SECONDS );

    // 5回失敗したらログを記録
    if ( $failures + 1 >= 5 ) {
        error_log( sprintf(
            '[WP Security] ブルートフォース疑い IP:%s user:%s 試行回数:%d',
            $ip, $username, $failures + 1
        ) );
    }
} );

// ログイン試行前にIPをチェックしてブロック
add_filter( 'authenticate', function( $user, $username, $password ) {
    $ip       = sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '' );
    $key      = 'login_fail_' . md5( $ip );
    $failures = (int) get_transient( $key );

    if ( $failures >= 5 ) {
        return new WP_Error(
            'too_many_attempts',
            __( 'ログイン試行回数が上限を超えました。15分後に再試行してください。' )
        );
    }

    return $user;
}, 30, 3 );

// ログイン成功時にカウンターをリセット
add_action( 'wp_login', function() {
    $ip  = sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '' );
    $key = 'login_fail_' . md5( $ip );
    delete_transient( $key );
} );

ステップ2:xmlrpc.phpを無効化する

// functions.php: XML-RPCを完全に無効化
add_filter( 'xmlrpc_enabled', '__return_false' );

// XML-RPCのメソッドをすべてブロック
add_filter( 'xmlrpc_methods', function( $methods ) {
    return []; // 空配列を返してすべてのメソッドを無効化
} );
# .htaccess: XML-RPCへのアクセスを403で拒否(より確実)
<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
</Files>

# または特定IPのみ許可
<Files xmlrpc.php>
    Order Deny,Allow
    Deny from all
    Allow from 203.0.113.0/24
</Files>

ステップ3:ログインURLを変更する

// functions.php: wp-login.phpへのアクセスをブロックしカスタムURLにリダイレクト
// ※ WPS Hide Loginプラグインが簡単だが、自前実装の例:

// カスタムログインURLを設定
define( 'CUSTOM_LOGIN_SLUG', 'my-secret-login' ); // wp-config.phpで定義推奨

add_action( 'init', function() {
    $slug = defined( 'CUSTOM_LOGIN_SLUG' ) ? CUSTOM_LOGIN_SLUG : 'login';

    // カスタムURLへのアクセスをwp-login.phpに内部転送
    if ( isset( $_GET[ $slug ] ) || $_SERVER['REQUEST_URI'] === '/' . $slug ) {
        // ログインフォームを表示する処理
        // ※ 完全な実装はWPS Hide Loginプラグイン等を推奨
    }
} );

// wp-login.phpへの直接アクセスを403にする(.htaccessで設定)
# .htaccess: wp-login.phpへの直接アクセスをブロック(特定IPのみ許可)
<Files wp-login.php>
    Order Deny,Allow
    Deny from all
    Allow from 203.0.113.1    # 自分のIPアドレスのみ許可
    Allow from 192.168.0.0/24 # オフィスのIPレンジ
</Files>

ステップ4:二段階認証(2FA)を設定する

// Google Authenticator / Two Factor プラグインの設定例
// プラグイン: Two-Factor (wordpress.org/plugins/two-factor/)

// プラグインなしの簡易TOTP実装(教育目的)
// 実運用では Two-Factor プラグインを推奨

// ログイン後に2FAコードを要求するフック
add_action( 'wp_login', function( $user_login, $user ) {
    // 2FA設定済みユーザーかチェック
    $secret = get_user_meta( $user->ID, 'totp_secret', true );
    if ( ! $secret ) {
        return; // 2FA未設定ならスキップ
    }

    // セッションに未認証フラグを設定してリダイレクト
    wp_set_current_user( 0 ); // 一時的にログアウト状態に
    wp_safe_redirect( home_url( '/2fa-verify/?uid=' . $user->ID ) );
    exit;
}, 10, 2 );

// メール認証コードを使った簡易2FA
add_action( 'wp_login', function( $user_login, $user ) {
    $code = wp_generate_password( 6, false, false );
    update_user_meta( $user->ID, '2fa_code', $code );
    update_user_meta( $user->ID, '2fa_expires', time() + 600 ); // 10分有効

    wp_mail(
        $user->user_email,
        '認証コード',
        "ログイン認証コード: {$code}\n\n10分以内に入力してください。"
    );
}, 10, 2 );

ステップ5:セキュリティヘッダーと追加の強化設定

// functions.php: セキュリティ強化の追加設定

// WordPressのバージョンを非表示
remove_action( 'wp_head', 'wp_generator' );

// ログインエラーメッセージを汎用化(ユーザー名/パスワードのヒントを隠す)
add_filter( 'login_errors', function() {
    return 'ログイン情報が正しくありません。';
} );

// ユーザー名の列挙を防ぐ(author=1 のURLへのアクセスをブロック)
add_action( 'init', function() {
    if ( ! is_admin() && isset( $_GET['author'] ) ) {
        wp_die( 'アクセスが拒否されました。', 403 );
    }
} );

// REST APIのユーザーリストエンドポイントを保護
add_filter( 'rest_endpoints', function( $endpoints ) {
    if ( isset( $endpoints['/wp/v2/users'] ) && ! current_user_can( 'list_users' ) ) {
        unset( $endpoints['/wp/v2/users'] );
        unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
    }
    return $endpoints;
} );

// 管理者以外が/wp-admin/にアクセスした場合はトップにリダイレクト
add_action( 'admin_init', function() {
    if ( ! current_user_can( 'edit_posts' ) && ! wp_doing_ajax() ) {
        wp_safe_redirect( home_url() );
        exit;
    }
} );

注意事項

  • IPによるアクセス制限(.htaccessでAllowリスト)を設定する場合、動的IPでは自分自身もブロックされる可能性があります。固定IPがない場合は試行回数制限プラグインとVPN組み合わせが現実的です。
  • xmlrpc.phpを無効化するとJetpack・モバイルアプリ・一部のブログクライアントが使えなくなります。必要な場合は特定IPのみ許可する方法を選んでください。
  • ログインURLを変更した場合、URLを忘れるとサイトにアクセスできなくなります。変更したURLは必ず安全な場所に記録してください。FTP/SSHでファイルを変更すれば復旧できます。

まとめ

ログインセキュリティの強化は「ログイン試行回数をトランジェントで制限→xmlrpc.phpを.htaccessで403拒否→.htaccessで管理者IPのみwp-login.phpを許可→Two-Factorプラグインで二段階認証→バージョン情報・ユーザー名列挙をfunctions.phpで無効化」の流れで整備します。関連記事:WordPressのwp-config.phpをセキュアに設定する方法WordPressをHTTPSに移行する方法

お気軽にご相談ください

お見積りへ お問い合わせへ