2026年7月28日

2026年7月28日

WordPressのマルウェア感染を駆除・復旧する方法

はじめに

WordPressサイトに見覚えのないファイルが追加されている・管理画面に不審な管理者アカウントが増えている・Googleサーチコンソールで「このサイトはハッキングされている可能性があります」と表示された・サイトにアクセスすると別のURLにリダイレクトされる・記事の本文にスパムリンクが勝手に挿入されているといった問題は、マルウェアを完全に除去し、脆弱性を塞ぐことで解決できます。

症状・原因

  • 古いWordPress・プラグイン・テーマの脆弱性を突かれてファイルが改ざんされた
  • 推測されやすいパスワードで管理者アカウントが不正アクセスされた
  • wp-content/uploadsディレクトリにPHPファイルが配置されて実行された
  • データベースのwp_optionsテーブルのsiteurlhomeが書き換えられた

解決手順

ステップ1:感染状況を調査する

# 最近変更されたPHPファイルを確認(過去7日間)
find /var/www/html -name "*.php" -newer /var/www/html/wp-config.php -type f 2>/dev/null

# アップロードディレクトリ内のPHPファイル(本来は存在しないはず)
find /var/www/html/wp-content/uploads -name "*.php" -type f

# 不審な eval/base64_decode を含むファイルを検索
grep -r "eval(base64_decode" /var/www/html --include="*.php" -l
grep -r "eval(gzinflate"    /var/www/html --include="*.php" -l

# wp_options テーブルの siteurl/home を確認
wp option get siteurl
wp option get home

# 不審な管理者アカウントを確認
wp user list --role=administrator --format=table

# wp_users テーブルに不審なユーザーがいないか
wp user list --format=table

ステップ2:マルウェアを除去する

# 不審なPHPファイルを削除
find /var/www/html/wp-content/uploads -name "*.php" -delete

# WordPress コアファイルを公式版で上書き(バックアップ後に実行)
wp core download --force --skip-content

# プラグインを公式版で上書き
wp plugin update --all

# テーマを公式版で上書き
wp theme update --all

# 不審な管理者を削除
wp user delete {suspicious_user_id} --reassign={admin_user_id}

# データベースのマルウェアを検索・確認
wp db query "SELECT option_name, option_value FROM wp_options 
             WHERE option_value LIKE '%eval(%' 
             OR option_value LIKE '%base64_decode%' 
             LIMIT 20"

ステップ3:パスワードと認証キーをリセットする

// wp-config.php の認証キーを新しいものに更新
// https://api.wordpress.org/secret-key/1.1/salt/ から新しいキーを生成して貼り付け

// 管理者パスワードを強制変更
wp user update 1 --user_pass="$(openssl rand -base64 24)"

// 全ユーザーのセッションを強制ログアウト
wp eval "
\$users = get_users(['fields' => 'ID']);
foreach (\$users as \$user_id) {
    \$sessions = WP_Session_Tokens::get_instance(\$user_id);
    \$sessions->destroy_all();
}
echo 'All sessions destroyed.' . PHP_EOL;
"
// functions.php: 強力なパスワードポリシーを強制
add_action('user_profile_update_errors', function(WP_Error $errors, bool $update, stdClass $user): void {
    if (strlen($user->user_pass) < 16) {
        $errors->add('weak_password', 'パスワードは16文字以上にしてください。');
    }
    if (!preg_match('/[A-Z]/', $user->user_pass) ||
        !preg_match('/[0-9]/', $user->user_pass) ||
        !preg_match('/[^a-zA-Z0-9]/', $user->user_pass)) {
        $errors->add('weak_password', 'パスワードには大文字・数字・記号を含めてください。');
    }
}, 10, 3);

ステップ4:再感染を防ぐセキュリティ強化

// wp-config.php に追加するセキュリティ設定
define('DISALLOW_FILE_EDIT', true);   // テーマ・プラグインエディターを無効化
define('DISALLOW_FILE_MODS', true);   // ファイルの更新・インストールを無効化(本番環境)

// functions.php: ログイン試行回数を制限
add_filter('authenticate', function(?WP_User $user, string $username): ?WP_User {
    $ip        = $_SERVER['REMOTE_ADDR'] ?? '';
    $cache_key = 'login_attempts_' . md5($ip);
    $attempts  = (int) get_transient($cache_key);

    if ($attempts >= 5) {
        return new WP_Error('too_many_attempts', '試行回数が多すぎます。30分後に再試行してください。');
    }

    if (is_wp_error($user)) {
        set_transient($cache_key, $attempts + 1, 30 * MINUTE_IN_SECONDS);
    }

    return $user;
}, 30, 2);

ステップ5:.htaccessとファイルパーミッションを修正する

# ファイルパーミッションを正しく設定
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
chmod 600 /var/www/html/wp-config.php

# アップロードディレクトリでのPHP実行を禁止
cat > /var/www/html/wp-content/uploads/.htaccess << 'EOF'
<Files "*.php">
    Order Deny,Allow
    Deny from all
</Files>
EOF

# wp-config.php へのアクセスを禁止
# .htaccess に追加:
# <Files wp-config.php>
#     Order Allow,Deny
#     Deny from all
# </Files>

# xmlrpc.php を無効化(ブルートフォース攻撃の入口)
wp eval "echo apply_filters('xmlrpc_enabled', true) ? 'enabled' : 'disabled';"
// xmlrpc.php を完全に無効化
add_filter('xmlrpc_enabled', '__return_false');

// REST API を未認証ユーザーに制限
add_filter('rest_authentication_errors', function(?WP_Error $result): ?WP_Error {
    if (!is_user_logged_in() && !is_null($result)) {
        return new WP_Error('rest_not_logged_in', '認証が必要です', ['status' => 401]);
    }
    return $result;
});

注意事項

  • マルウェア除去作業は必ずサイトをメンテナンスモードにしてから行ってください。作業中に別の改ざんが発生する可能性があります
  • DISALLOW_FILE_MODS=trueを設定するとWordPress管理画面からのプラグイン・テーマの更新ができなくなります。更新時は一時的に無効化してください

まとめ

WordPress マルウェア感染の解決は①findで最近変更されたPHPファイルを確認・grepeval(base64_decodeを含むファイルを特定・不審な管理者アカウントをwp user listで確認、②wp core download --forceでコアファイルを公式版で上書き・アップロードディレクトリのPHPファイルを削除・不審な管理者をwp user deleteで削除、③wp-config.phpの認証キーを再生成・全管理者のパスワードを強制変更・WP_Session_Tokens::destroy_all()で全セッションを無効化、④DISALLOW_FILE_EDIT/MODS=trueでファイル編集を禁止・authenticateフィルターでログイン試行回数を制限・wp_mailで不正ログインを通知、⑤ファイルパーミッションを644/755に修正・uploads/.htaccessでPHP実行を禁止・xmlrpc_enabledフィルターでXML-RPC無効化の手順で解決します。

お気軽にご相談ください

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