2026年5月20日
2026年5月20日
WordPressプラグインの脆弱性をチェックする方法|WP-CLI・WPScan・Wordfenceと定期確認
WordPress サイトへの侵入で多いのは、プラグインやテーマの既知の脆弱性を突く攻撃です。脆弱性の多くは修正版が出ているので、「どのプラグインの、どのバージョンが入っているか」を把握し、脆弱性情報と照らし合わせて更新するのが基本の対策になります。
この記事の WP-CLI のコマンドは WP-CLI 本体のヘルプ、WPScan の API と料金は wpscan.com、Wordfence の機能は wordpress.org のプラグインページで2026年10月時点の内容を確認しています。
確認の流れ
| 段階 | やること | 使う道具 |
|---|---|---|
| 1 | 入っているプラグインとバージョン、更新の有無を一覧にする | 管理画面、WP-CLI |
| 2 | 公開停止になったプラグイン、改ざんされたファイルがないか確かめる | WP-CLI |
| 3 | 既知の脆弱性と照合する | WPScan、Wordfence など |
| 4 | 更新・停止・削除で対処する | 管理画面、WP-CLI |
| 5 | 定期的に繰り返す | 自動更新、WP-Cron、通知 |
手順1: プラグインの一覧と更新の有無を確認する
管理画面では「プラグイン」→「インストール済みプラグイン」で、更新があるプラグインに「新しいバージョンの○○が利用できます」と表示されます。サーバーに SSH で入れるなら、WP-CLI で一覧にすると記録を残しやすくなります。
# 名前・有効/無効・現在のバージョン・更新後のバージョン・自動更新の設定
wp plugin list --fields=name,status,version,update_version,auto_update
# 更新があるプラグインだけ
wp plugin list --update=available
# 無効化されているプラグイン(削除の候補)
wp plugin list --status=inactive
手順2: 公開停止と改ざんを確認する
wordpress.org のプラグインディレクトリでは、未修正のセキュリティ問題などを理由にプラグインが公開停止(closed)になることがあります。公開停止になると更新が配信されないため、管理画面に更新の通知が出ないまま古いバージョンが残ります。
# wordpress.org での状態と最終更新日
wp plugin list --fields=name,version,wporg_status,wporg_last_updated
wporg_status が closed のプラグインは、代わりのプラグインへの移行を検討します。空欄のものは wordpress.org 以外から入れたプラグイン(有料プラグインなど)で、配布元のサイトで更新情報を確認します。
ファイルが改ざんされていないかは、wordpress.org に登録されている元のファイルとの照合で確かめられます。
# すべてのプラグインを照合(wordpress.org で配布されているものだけが対象)
wp plugin verify-checksums --all
# WordPress 本体も照合する
wp core verify-checksums
照合で差分が見つかったファイルは、改ざんの可能性があります。バックアップを取ったうえで、そのプラグインを wordpress.org から入れ直すと元のファイルに戻ります。
手順3: 既知の脆弱性と照合する
WPScan(コマンドラインのスキャナー)
WPScan は、外部からサイトを調べて WordPress 本体・プラグイン・テーマのバージョンを推定し、WPScan の脆弱性データベースと照合するツールです。スキャナー自体は無料ですが、脆弱性の照合には API トークンが必要です。wpscan.com の料金ページ(2026年10月時点)では、無料の Researcher プランは非営利の利用に限られ、API の呼び出しは1日25回までです。業務で使う場合は有料のライセンスが必要です。
# 公式の Docker イメージで実行する例(自分が管理するサイトだけを対象にする)
docker run -it --rm wpscanteam/wpscan \
--url https://example.com \
--enumerate vp \
--api-token YOUR_API_TOKEN
--enumerate vpは「脆弱性が登録されているプラグイン」だけを表示します。pにするとプラグインを広く列挙します。--plugins-detection aggressiveを付けると検出漏れは減りますが、サイトに大量のリクエストを送ります。他人のサイトに対しては実行しないでください。- 結果を JSON で保存するには
--format json --output result.jsonを付けます。
JSON から、脆弱性があるプラグインだけを取り出す例です。
import json
with open("result.json", encoding="utf-8") as f:
data = json.load(f)
for slug, plugin in (data.get("plugins") or {}).items():
vulns = plugin.get("vulnerabilities") or []
if not vulns:
continue
version = (plugin.get("version") or {}).get("number", "不明")
print(f"== {slug} (検出バージョン: {version}) ==")
for v in vulns:
print(" -", v.get("title"), "/ 修正バージョン:", v.get("fixed_in") or "未修正")
WPScan の詳しい使い方は WPScanでWordPressの脆弱性を診断する方法 を参照してください。
Wordfence(プラグインのスキャナー)
サーバーにツールを入れられない場合は、Wordfence のスキャンで確認できます。wordpress.org のプラグインページによると、Wordfence のスキャンは既知の脆弱性があるプラグイン・テーマを検出して知らせます。スキャンの設定は Wordfenceのスキャン機能 で説明しています。
手で確かめる
特定のプラグインについて調べたいときは、プラグイン名で WPScan の脆弱性データベース(wpscan.com)や Wordfence Intelligence、Patchstack の公開データベースを検索し、「影響を受けるバージョン」と「修正バージョン」を自分のバージョンと比べます。
手順4: 見つかったときの対処
| 状況 | 対処 |
|---|---|
| 修正版が出ている | バックアップを取ってから更新する。更新後に表側と管理画面の主な操作を確認する |
| 修正版が出ていない | 代わりのプラグインに移るか、それまで無効化する。WAF で該当の攻撃を遮断できる場合もある |
| 公開停止(closed) | 修正の見込みが立つまで、代わりのプラグインへの移行を検討する |
| 使っていない | 無効化だけでなく削除する。無効でもファイルが残っていれば、直接アクセスで攻撃される場合がある |
# 更新する前にデータベースのバックアップを取る
wp db export backup-before-update.sql
# 特定のプラグインを更新する
wp plugin update contact-form-7
# 更新があるものをまとめて更新する
wp plugin update --all
更新で表示が崩れたときの戻し方は プラグインの更新で不具合が出たときの対処 を参照してください。
手順5: 定期的に確認する
自動更新を使う
WordPress 5.5 以降は、「プラグイン」→「インストール済みプラグイン」の「自動更新を有効化」で、プラグインごとに自動更新できます。自動更新が行われると、管理者のメールアドレスに結果が送られます。WP-CLI では次のとおりです。
wp plugin auto-updates enable contact-form-7
wp plugin auto-updates status --all
WPScan API で週1回チェックしてメールで知らせる
自動更新を使わないプラグインがある場合は、WP-Cron で WPScan API に問い合わせ、修正版より古いバージョンが入っていたらメールで知らせることができます。API トークンは wp-config.php に定数で書きます(コードやデータベースに直接書かない)。
// wp-config.php(/* That's all, stop editing! */ の行より上)
define( 'WPSCAN_API_TOKEN', 'ここにAPIトークン' );
次のコードは、サイト用の独自プラグインか functions.php に置きます。プラグイン1つにつき API を1回呼ぶので、無料プランの1日25回を超えないよう、対象のプラグイン数に注意してください。
<?php
// 週1回の予定を登録する
function mysite_schedule_vuln_check() {
if ( ! wp_next_scheduled( 'mysite_weekly_vuln_check' ) ) {
wp_schedule_event( time(), 'weekly', 'mysite_weekly_vuln_check' );
}
}
add_action( 'init', 'mysite_schedule_vuln_check' );
function mysite_run_vuln_check() {
if ( ! defined( 'WPSCAN_API_TOKEN' ) || '' === WPSCAN_API_TOKEN ) {
return;
}
// WP-Cron の中では get_plugins() が読み込まれていないため読み込む
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$found = array();
foreach ( get_plugins() as $file => $data ) {
$slug = dirname( $file );
if ( '.' === $slug ) {
continue; // フォルダーに入っていない単体ファイルのプラグインは対象外
}
$response = wp_remote_get(
'https://wpscan.com/api/v3/plugins/' . rawurlencode( $slug ),
array(
'headers' => array( 'Authorization' => 'Token token=' . WPSCAN_API_TOKEN ),
'timeout' => 15,
)
);
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
continue; // 通信エラー、またはデータベースに無いプラグイン
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
$vulns = isset( $body[ $slug ]['vulnerabilities'] ) ? $body[ $slug ]['vulnerabilities'] : array();
foreach ( $vulns as $vuln ) {
$fixed_in = isset( $vuln['fixed_in'] ) ? $vuln['fixed_in'] : '';
if ( '' === (string) $fixed_in || version_compare( $data['Version'], $fixed_in, '<' ) ) {
$found[] = sprintf(
"%s %s\n %s\n 修正バージョン: %s",
$data['Name'],
$data['Version'],
isset( $vuln['title'] ) ? $vuln['title'] : '(タイトルなし)',
'' === (string) $fixed_in ? '未修正' : $fixed_in
);
}
}
}
if ( $found ) {
wp_mail(
get_option( 'admin_email' ),
'[' . wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ) . '] 脆弱性が登録されているプラグインがあります',
implode( "\n\n", $found ) . "\n\nプラグインの管理画面: " . admin_url( 'plugins.php' )
);
}
}
add_action( 'mysite_weekly_vuln_check', 'mysite_run_vuln_check' );
- WP-Cron はサイトへのアクセスがあったときに動くため、アクセスが少ないサイトでは実行が遅れます。サーバーの cron から
wp cron event run --due-nowを実行すると時間どおりに動きます。 - 動作確認は
wp cron event run mysite_weekly_vuln_checkで、その場で実行できます。 - 有料プラグインなど、WPScan のデータベースにスラッグが無いプラグインは照合されません。
- コードを外すときは、
wp_clear_scheduled_hook( 'mysite_weekly_vuln_check' )で予定も消します。
使っていないプラグインとテーマを削除する
# 無効化されているプラグインを確認してから削除する
wp plugin list --status=inactive --field=name
wp plugin delete hello-dolly akismet
# 使っていないテーマを確認する
wp theme list --status=inactive
wp plugin delete $(wp plugin list --status=inactive --field=name)で無効なプラグインをまとめて消せますが、一時的に止めているだけのプラグインも消えます。一覧を確認してから名前を指定する方が安全です。- 削除してもプラグインが作ったデータベースのテーブルやオプションは残ることがあります。必要ならプラグインの説明に従って削除します。
- テーマは、子テーマの親テーマを消さないよう注意してください。有効なテーマが壊れたときの予備として、デフォルトテーマ(Twenty Twenty-Five など)を1つ残しておくと安心です。
まとめ
wp plugin listで更新の有無とwporg_status(公開停止)を確認し、wp plugin verify-checksums --allで改ざんを調べる- 既知の脆弱性は WPScan(無料 API は非営利・1日25回)や Wordfence のスキャンで照合する
- 修正版があれば更新、無ければ代替か無効化。使っていないプラグインは削除する
- 自動更新、または WP-Cron と WPScan API による週1回の確認で、定期的に見直す