2026年5月20日

2026年5月20日

WordPressのプラグインの脆弱性をチェックする方法

はじめに

WordPressプラグインの脆弱性は攻撃者に悪用される主要な侵入経路です。インストール済みプラグインのバージョンを把握し、既知の脆弱性(CVE)がないか定期的に確認することで、被害を未然に防げます。

症状・原因

  • インストールしているプラグインに脆弱性があるか確認したい
  • プラグインを更新したら問題が起きそうで更新を後回しにしている
  • 使われていない古いプラグインが放置されている
  • 脆弱性情報をメールで受け取る仕組みがない

解決手順

ステップ1:インストール済みプラグインの状態を確認する

# インストール済みプラグイン一覧(バージョン・ステータス付き)
wp plugin list --fields=name,version,status,update

# 更新が必要なプラグインのみ表示
wp plugin list --update=available --format=table

# 無効化されているプラグインを確認(削除候補)
wp plugin list --status=inactive --format=table

# プラグインのファイル整合性チェック
wp plugin verify-checksums --all

# 特定のプラグインのチェック
wp plugin verify-checksums contact-form-7

# プラグインの詳細情報(最終更新日・WordPress互換性)
wp plugin get contact-form-7 --fields=name,version,author,update_version

ステップ2:脆弱性データベースで確認する

# WPScan で脆弱性スキャン(APIトークン必須)
wpscan --url https://example.com \
    --enumerate p \
    --api-token YOUR_API_TOKEN \
    --plugins-detection aggressive

# JSON形式で出力して解析
wpscan --url https://example.com \
    --enumerate p \
    --api-token YOUR_API_TOKEN \
    --output /tmp/plugin-scan.json \
    --format json

# 脆弱性のみを抽出
python3 -c "
import json
with open('/tmp/plugin-scan.json') as f:
    data = json.load(f)
for name, plugin in data.get('plugins', {}).items():
    vulns = plugin.get('vulnerabilities', [])
    if vulns:
        print(f'=== {name} ===')
        for v in vulns:
            print(f'  [{v[\"cvss\"][\"score\"]}] {v[\"title\"]}')
            print(f'  Fixed in: {v.get(\"fixed_in\", \"未修正\")}')
"

ステップ3:脆弱性チェックを WordPress に統合する

// functions.php: プラグイン脆弱性チェック通知

// ① プラグイン更新時に古いバージョンの脆弱性を警告
add_action('admin_notices', function(): void {
    if (!current_user_can('update_plugins')) return;

    // 更新が必要なプラグインの数を取得
    $update_data = get_site_transient('update_plugins');
    if (!$update_data || empty($update_data->response)) return;

    $count = count($update_data->response);
    if ($count > 0) {
        echo '<div class="notice notice-warning is-dismissible">';
        echo '<p><strong>' . $count . '件のプラグイン更新があります。</strong>';
        echo 'セキュリティ上の理由から早急に更新してください。';
        echo ' <a href="' . admin_url('plugins.php?plugin_status=upgrade') . '">今すぐ更新</a></p>';
        echo '</div>';
    }
});

// ② プラグインインストール・更新のログを記録
add_action('upgrader_process_complete', function(\WP_Upgrader $upgrader, array $hook_extra): void {
    if ($hook_extra['action'] !== 'update' || $hook_extra['type'] !== 'plugin') return;

    $plugins = $hook_extra['plugins'] ?? [];
    $admin_email = get_option('admin_email');
    $message = "以下のプラグインが更新されました:\n\n";

    foreach ($plugins as $plugin_file) {
        $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file, false, false);
        $message .= "・{$plugin_data['Name']} → v{$plugin_data['Version']}\n";
    }
    $message .= "\n更新時刻: " . current_time('Y-m-d H:i:s');

    wp_mail($admin_email, '[WordPress] プラグイン更新完了', $message);
}, 10, 2);

ステップ4:脆弱なプラグインを自動検出・通知する

// functions.php: 週次で脆弱性チェックを実行

add_action('wp', function(): void {
    if (!wp_next_scheduled('weekly_plugin_vuln_check')) {
        wp_schedule_event(time(), 'weekly', 'weekly_plugin_vuln_check');
    }
});

add_action('weekly_plugin_vuln_check', function(): void {
    // WPScan API で脆弱性を確認
    $api_token = defined('WPSCAN_API_TOKEN') ? WPSCAN_API_TOKEN : '';
    if (empty($api_token)) return;

    $installed_plugins = get_plugins();
    $vulnerable_plugins = [];

    foreach ($installed_plugins as $plugin_file => $plugin_data) {
        $slug = dirname($plugin_file);
        if ($slug === '.') continue;

        // WPScan API でプラグインの脆弱性を確認
        $response = wp_remote_get(
            "https://wpscan.com/api/v3/plugins/{$slug}",
            [
                'headers' => ['Authorization' => "Token token={$api_token}"],
                'timeout' => 10,
            ]
        );

        if (is_wp_error($response)) continue;

        $body = json_decode(wp_remote_retrieve_body($response), true);
        $current_version = $plugin_data['Version'];

        foreach ($body[$slug]['vulnerabilities'] ?? [] as $vuln) {
            $fixed_in = $vuln['fixed_in'] ?? null;
            if (!$fixed_in || version_compare($current_version, $fixed_in, '<')) {
                $vulnerable_plugins[] = [
                    'name' => $plugin_data['Name'],
                    'version' => $current_version,
                    'vuln' => $vuln['title'],
                    'fixed_in' => $fixed_in ?? '未修正',
                ];
            }
        }
    }

    if (!empty($vulnerable_plugins)) {
        $body = "脆弱性のあるプラグインが見つかりました:\n\n";
        foreach ($vulnerable_plugins as $item) {
            $body .= "プラグイン: {$item['name']} (v{$item['version']})\n";
            $body .= "脆弱性: {$item['vuln']}\n";
            $body .= "修正バージョン: {$item['fixed_in']}\n\n";
        }
        $body .= "直ちにプラグインを更新してください:\n" . admin_url('plugins.php?plugin_status=upgrade');

        wp_mail(
            get_option('admin_email'),
            '[警告] WordPress プラグイン脆弱性検出',
            $body
        );
    }
});

ステップ5:使われていないプラグインを削除する

# 無効化されているプラグインを一覧表示
wp plugin list --status=inactive

# 無効化されているプラグインを全削除
wp plugin delete $(wp plugin list --status=inactive --field=name)

# 特定のプラグインを削除
wp plugin delete hello-dolly

# 有効化していないテーマも削除(デフォルトテーマを除く)
wp theme list --status=inactive
wp theme delete twentytwenty twentytwentyone

# 削除後に整合性を再確認
wp plugin verify-checksums --all
wp core verify-checksums

注意事項

  • プラグインを削除する前に必ずバックアップを取ってください。削除したプラグインが作成したデータベーステーブルは自動では削除されない場合があります
  • WPSCAN_API_TOKENwp-config.phpdefine('WPSCAN_API_TOKEN', 'your_token');として定義してください。コードに直接書かないようにしてください
  • 無効化されていてもプラグインファイルが存在すると攻撃対象になります。使用しないプラグインは無効化だけでなく削除してください

まとめ

プラグイン脆弱性チェックは①wp plugin list --update=availableで更新が必要なプラグインを確認、②wp plugin verify-checksums --allでファイル整合性を検証、③WPScan APIで既知CVEをスキャンしてJSON出力を解析、④weekly_plugin_vuln_check cronで週次自動チェック・脆弱性発見時にメール通知、⑤使用していないプラグインをwp plugin deleteで削除してリスクを最小化します。

お気軽にご相談ください

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