2026年8月5日

2026年8月5日

WordPressのセキュリティログと監視の設定方法:何を記録し、どう気づくか

WordPress のセキュリティログと監視は、「ログイン・ユーザー・プラグイン・ファイルの変化を記録する」「記録をサーバーの外にも残す」「異常があったときに通知が届くようにする」の 3 段階で考えると整理できます。この記事では、記録すべきイベントの選び方、プラグインでの導入、コードでの記録、サーバーログとの組み合わせ、改ざんの定期検査と通知までを順に説明します。

なぜログと監視が必要なのか

不正アクセスの被害は、気づくまでの時間が長いほど大きくなります。管理者ユーザーを追加されたり、プラグインのファイルにコードを埋め込まれたりしても、表示上は何も変わらないことが多く、検索結果にスパムが出たり、サーバー会社から連絡が来たりして初めて発覚する例も珍しくありません。

ログがあれば、「いつ」「どのアカウントで」「何が変わったか」を後から追跡でき、侵入経路の特定や復旧範囲の判断ができます。さらに監視(通知)を組み合わせれば、被害が広がる前に気づけます。WordPress 本体は、ログイン履歴や設定変更の履歴を管理画面に残す機能を標準では持っていないため、プラグインやサーバー側の仕組みで補う必要があります。

記録すべきイベント

すべてを記録するとログが膨大になり、見返さなくなります。まずは攻撃の兆候や結果が表れやすい次のイベントに絞ります。

  • ログイン:成功と失敗、どのユーザー名で、どの IP アドレスから
  • ユーザー:新規作成、削除、ロールの変更、メールアドレスやパスワードの変更
  • プラグイン・テーマ:インストール、有効化・無効化、更新、ファイルエディターでの編集
  • 設定:サイトの URL、管理者メールアドレス、ユーザー登録の可否などの変更
  • ファイル:本体・プラグインのファイルの改ざん、uploads への PHP ファイルの追加

特に「深夜に管理者ユーザーが作られた」「普段使わないアカウントでログインがあった」「見覚えのないプラグインが有効化された」は、侵入後によく見られる動きです。

プラグインで管理画面に記録を残す

最も手軽なのは、アクティビティログ系のプラグインを使う方法です。代表的なものに WP Activity Log、Simple History があり、上で挙げたログイン・ユーザー・プラグイン・設定の変更を管理画面から一覧できます。メール通知や外部サービスへの転送、保存期間の設定は、プラグインによって有料版の機能になっていることがあります(2026年10月現在)。

導入したら、次の点を確認しておきます。

  • 保存期間:ログはデータベースに保存されるため、無期限にするとテーブルが肥大化します。90 日〜1 年程度を目安に、運用に合わせて決めます。
  • 閲覧権限:ログには IP アドレスなどの情報が含まれるので、閲覧できるのは管理者だけにします。
  • 限界を理解する:管理画面のログは、管理者権限を奪われると攻撃者に消される可能性があります。次に説明するように、サーバー側にも記録を残しておくと安心です。

コードでサーバーのログに記録する

プラグインを増やしたくない場合や、サーバー側のログと一緒に管理したい場合は、WordPress のフックを使って syslog に書き出す方法があります。syslog に送った記録は Web サーバーのドキュメントルートの外に保存されるため、WordPress の管理画面からは消せません。次のコードを wp-content/mu-plugins/security-log.php として保存すると、プラグイン一覧から無効化されることもありません。

<?php
/**
 * Plugin Name: Security Log
 * Description: ログインやロール変更などを syslog に記録する
 */

function myplugin_security_log( $event, array $context = array() ) {
    $context['ip'] = isset( $_SERVER['REMOTE_ADDR'] )
        ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) )
        : '';

    openlog( 'wordpress-security', LOG_PID, LOG_AUTH );
    syslog( LOG_NOTICE, wp_json_encode( array( 'event' => $event ) + $context ) );
    closelog();
}

// ログイン失敗
add_action( 'wp_login_failed', function ( $username ) {
    myplugin_security_log( 'login_failed', array( 'user' => $username ) );
} );

// ログイン成功
add_action( 'wp_login', function ( $user_login, $user ) {
    myplugin_security_log( 'login_success', array( 'user' => $user_login, 'roles' => $user->roles ) );
}, 10, 2 );

// ロールの変更
add_action( 'set_user_role', function ( $user_id, $role, $old_roles ) {
    myplugin_security_log( 'role_changed', array( 'user_id' => $user_id, 'new' => $role, 'old' => $old_roles ) );
}, 10, 3 );

// 新規ユーザーの作成
add_action( 'user_register', function ( $user_id ) {
    myplugin_security_log( 'user_registered', array( 'user_id' => $user_id, 'by' => get_current_user_id() ) );
} );

// プラグインの有効化
add_action( 'activated_plugin', function ( $plugin ) {
    myplugin_security_log( 'plugin_activated', array( 'plugin' => $plugin, 'by' => get_current_user_id() ) );
} );

Debian・Ubuntu 系で rsyslog が動いている環境なら、LOG_AUTH で送った記録は /var/log/auth.log に、systemd の journal には識別子 wordpress-security で残ります。journalctl -t wordpress-security --since today で当日分を確認できます。

使うときの注意点は次のとおりです。

  • プロキシ配下の IP アドレス:Cloudflare やロードバランサーの後ろにあるサーバーでは、REMOTE_ADDR にプロキシの IP が入ります。実際の接続元を記録するには、Web サーバー側で信頼できるプロキシからのヘッダーだけを使って接続元を復元する設定(Nginx の real_ip モジュールなど)を先に行います。ヘッダーを PHP で直接読むと、偽装された値を記録してしまいます。
  • ユーザー名欄の入力:ログイン失敗時のユーザー名には、利用者が誤ってパスワードを入力した文字列が入ることがあります。ログの閲覧者と保存期間を限定してください。
  • 共有サーバー:レンタルサーバーでは syslog が使えない、または記録を見られないことがあります。その場合はプラグインのログとサーバー会社が提供するアクセスログで代用します。

サーバーのアクセスログで攻撃の兆候を見る

WordPress のログに加えて、Web サーバーのアクセスログも監視の材料になります。たとえば、wp-login.php や xmlrpc.php に大量の POST が来ていれば、パスワード総当たり攻撃の可能性があります。Nginx の標準的なログ形式なら、次のコマンドで接続元ごとの回数を数えられます。

# wp-login.php と xmlrpc.php への POST を送信元 IP ごとに数え、多い順に表示する
awk '$6 ~ /POST/ && $7 ~ /wp-login\.php|xmlrpc\.php/ {print $1}' /var/log/nginx/access.log \
  | sort | uniq -c | sort -rn | head -20

ログの列の位置はログ形式の設定によって変わるので、自分の環境のログを 1 行見て確認してから使ってください。手作業で数えるのではなく自動で遮断したい場合は、fail2ban でアクセスログを監視し、一定回数を超えた IP をファイアウォールで一時的にブロックする構成がよく使われます。

ファイルの改ざんを定期的に検査する

ログイン記録だけでは、脆弱性を突いて直接ファイルを書き換えられた場合に気づけません。WP-CLI の verify-checksums を使うと、WordPress 本体と WordPress.org で配布されているプラグインのファイルを公式のチェックサムと照合できます。

# 毎日 4 時に本体とプラグインのファイルを検査し、不一致があればメールで通知する(crontab の例)
0 4 * * * cd /var/www/html && (wp core verify-checksums --quiet && wp plugin verify-checksums --all --quiet) || echo "WordPress checksum mismatch on $(hostname)" | mail -s "WP checksum alert" admin@example.com

この cron は、WordPress のファイルを所有するユーザー(www-data など)の crontab に登録します。root で WP-CLI を実行すると警告が出て止まります。mail コマンドを使うにはサーバーからメールを送れる設定が必要です。有料プラグインやテーマは WordPress.org にチェックサムがないため、この方法では検査できません。検査できないプラグインがあると毎回エラー扱いになり通知が届き続けることがあるので、その場合は --exclude=プラグインのスラッグ で対象から外します。一度手動で実行して、出力と終了の仕方を確かめてから cron に登録してください。

ログを外に送り、通知を設定する

攻撃者がサーバーの管理者権限まで得た場合、サーバー内のログも消される可能性があります。重要なログは、rsyslog の転送機能や、ログ収集サービス(Grafana Loki、クラウド事業者のログサービスなど)を使って、別のサーバーにも送っておくのが理想です。

通知は、多すぎると見なくなります。最初は次の 3 つ程度に絞るのがおすすめです。

  1. 管理者ロールのユーザーが作成された、またはロールが管理者に変更された
  2. プラグインが新しくインストール・有効化された
  3. ファイルのチェックサム検査で不一致が出た

あわせて、サーバーの時刻が NTP で同期されているかと、タイムゾーンが揃っているかも確認しておきます。WordPress のログ、Web サーバーのログ、WAF のログで時刻がずれていると、後から突き合わせるときに追跡が難しくなります。

まとめ

  • 記録するのは、ログイン、ユーザーとロールの変更、プラグインの変更、設定の変更、ファイルの改ざんを中心にします。
  • 手軽に始めるならアクティビティログ系のプラグイン、消されにくくするなら syslog など WordPress の外にも記録します。
  • アクセスログでは wp-login.php と xmlrpc.php への大量の POST が総当たり攻撃の兆候です。
  • WP-CLI の verify-checksums を cron で動かし、改ざんを定期的に検査します。
  • 通知は重要なイベントに絞り、ログはサーバーの外にも送っておきます。

お気軽にご相談ください

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