WordPressで企業サイト・ブログを運用しているWeb担当者、制作会社の保守担当者向けの記事です。
2026年9月22日、WordPress本体(コア)の脆弱性 CVE-2026-87902 を修正したセキュリティリリース 7.1.2 が公開されました。ログイン不要で、条件がそろうとリモートからのコード実行(RCE)につながります。修正公開の当日から攻撃が観測されています。
この記事では「自分のサイトは更新済みか」「RCEの前提条件がそろっているか」「すでに踏まれていないか」を、コピペで確認できるコマンド付きでまとめます。
何が起きたのか
| 項目 | 内容 |
|---|---|
| CVE | CVE-2026-87902(GitHub Advisory: GHSA-7hp8-65ch-5whp) |
| 種別 | パストラバーサルによるローカルPHPファイルの読み込み(CWE-98:include/require に渡すファイル名の制御不備) |
| 認証 | 不要(ユーザー操作も不要) |
| 影響バージョン | 4.7.0 〜 7.1.1(約9年分) |
| 修正版 | 7.1.2 ほか、4.7 系までの全ブランチにバックポート |
| 深刻度 | CVSS v4.0 9.2(Critical) |
| 悪用状況 | 2026-09-25 に米CISAが KEV(悪用が確認された脆弱性カタログ) へ追加 |
公式発表(WordPress 7.1.2 Release)によると、未認証の攻撃者が条件次第で、固定ページのテンプレートを決める処理(get_page_template())に、有効化中テーマの外にある読み取り可能なPHPファイルを読み込ませられる、という問題です。URL から組み立てたテンプレート名に ../(上の階層へ戻る指定)のチェックが漏れていたことが原因とされています。
ポイントは3つです。
- 対象がほぼすべての現役サイト。 プラグインではなく本体の脆弱性なので、「プラグインは最小限にしている」サイトも対象です。
- RCEまで行くには前提条件がある。 ただし「該当しないはず」と判断するより、更新するほうが早く確実です。条件の確認は後述します。
- 修正と同時に技術的な詳細が公開され、攻撃が即座に始まった。 国内でもレンタルサーバー各社が注意喚起や強制アップデートを実施しています。自動更新が効いていない・止めているサイトは、今も未修正のまま残っている可能性があります。
攻撃の成立条件は確認に必要な範囲にとどめ、再現手順は扱いません。以下は「同じ被害を防ぐ」ための確認と対処です。
1. まずバージョンを確認する(1分)
WP-CLI が使える環境ならこれが最速です。
# 現在のコアバージョン
wp core version
# 同じブランチ内の更新(マイナー更新)があるか
wp core check-update --minor
管理画面なら「ダッシュボード → 更新」で確認できます。WP-CLI が無い環境では、コアに同梱されているバージョン定義ファイルを直接見ます。
# WordPress のドキュメントルートで実行
grep "wp_version =" wp-includes/version.php
修正版の早見表
自分のブランチの番号以上になっていれば修正済みです(GitHub Advisory 記載の修正版)。
| ブランチ | 修正版 | ブランチ | 修正版 |
|---|---|---|---|
| 7.1 | 7.1.2 | 5.9 | 5.9.18 |
| 7.0 | 7.0.6 | 5.8 | 5.8.17 |
| 6.9 | 6.9.9 | 5.7 | 5.7.19 |
| 6.8 | 6.8.10 | 5.6 | 5.6.21 |
| 6.7 | 6.7.9 | 5.5 | 5.5.22 |
| 6.6 | 6.6.9 | 5.4 | 5.4.23 |
| 6.5 | 6.5.12 | 5.3 | 5.3.25 |
| 6.4 | 6.4.12 | 5.2 | 5.2.28 |
| 6.3 | 6.3.12 | 5.1 | 5.1.26 |
| 6.2 | 6.2.13 | 5.0 | 5.0.29 |
| 6.1 | 6.1.14 | 4.9 | 4.9.33 |
| 6.0 | 6.0.16 | 4.8 | 4.8.32 |
| 4.7 | 4.7.37 |
古いブランチにも修正は届いていますが、公式に「積極的にサポートしているのは最新版のみ」とされています。今回をきっかけに、最新の 7.1 系へ上げる計画も立てておくのが安全です。
複数サイトをまとめて棚卸しする
保守契約で複数サイトを抱えている場合は、サーバー上の WordPress を一括で洗い出します。
# /var/www 配下の WordPress を探し、バージョンを一覧表示
find /var/www -name version.php -path '*/wp-includes/*' 2>/dev/null | while read -r f; do
printf '%s\t%s\n' "$(grep -oP "wp_version = '\K[^']+" "$f")" "${f%/wp-includes/version.php}"
done | sort -V
2. 対処:更新する
更新前にバックアップを取ります。
# DBとファイルのバックアップ(保存先は公開ディレクトリの外へ)
wp db export ~/backup-db-$(date +%Y%m%d).sql
tar czf ~/backup-files-$(date +%Y%m%d).tar.gz wp-content wp-config.php
同じブランチ内の修正版へ上げるだけなら、互換性への影響は小さいはずです。
# 同じブランチの最新修正版へ(例: 6.8.x → 6.8.10)
wp core update --minor
# DB の更新が必要な場合に備えて実行
wp core update-db
# 反映確認
wp core version
wp core verify-checksums
最新の 7.1.2 まで上げる場合は wp core update を使います。メジャー更新はテーマ・プラグインとの互換性に影響するため、ステージング環境で先に確認してから本番に当ててください。
自動更新が止まっていないか確認する
今回のようなセキュリティリリースは、通常はマイナー更新として自動で適用されます。それでも未修正のサイトが残る典型は、自動更新を設定で止めているケースです。
# wp-config.php で自動更新を止めていないか
grep -nE "AUTOMATIC_UPDATER_DISABLED|WP_AUTO_UPDATE_CORE|DISALLOW_FILE_MODS" wp-config.php
# テーマ・プラグインのフィルタでコア更新を止めていないか
grep -rnE "auto_update_core|automatic_updater_disabled|allow_minor_auto_core_updates" \
wp-content/themes wp-content/plugins wp-content/mu-plugins 2>/dev/null
AUTOMATIC_UPDATER_DISABLED が true、または WP_AUTO_UPDATE_CORE が false になっていれば、マイナー更新も止まっています。運用上の理由が無ければ、少なくともマイナー更新(セキュリティ修正)は自動で入る設定に戻します。
// wp-config.php:マイナー更新(セキュリティリリース)は自動適用する
define( 'WP_AUTO_UPDATE_CORE', 'minor' );
3. RCEの前提条件がそろっているか確認する
更新が済めば脆弱性そのものは塞がります。ここは「更新までの間に、自分のサイトがどれだけ危険だったか」を見積もり、次の節の痕跡調査をどこまで深くやるか決めるための確認です。
公式アドバイザリが示す前提条件は次の2つです。
-
有効化中のテーマ(親テーマ・子テーマ)の直下に、名前が
page-で始まるディレクトリがある(例:page-templates)。Twenty Twelve / Twenty Fourteen や、Neve / Hestia / Sydney などが該当すると報じられています。 -
サーバー上に、読み込まれると悪用の踏み台になる PHP ファイルがある。 代表例が PHP の付属ツール PEAR の
pearcmd.phpで、PHP のregister_argc_argv設定が On の環境では RCE につながるとされています。
テーマのディレクトリを見る
# 有効化中のテーマ(子テーマを使っている場合は親テーマも確認する)
wp theme list --status=active --fields=name,version
wp option get template # 親テーマ
wp option get stylesheet # 子テーマ(親と同じなら子テーマなし)
# テーマ直下に page- で始まるディレクトリがあるか
for t in "$(wp option get template)" "$(wp option get stylesheet)"; do
find "wp-content/themes/$t" -maxdepth 1 -type d -name 'page-*'
done
PHP の設定と PEAR を見る
register_argc_argv は CLI とWeb(PHP-FPM / mod_php)で値が違うことがあるため、Web 側の設定を確認します。
# PHP-FPM の場合(バージョン部分は環境に合わせる)
php-fpm8.3 -i 2>/dev/null | grep -i register_argc_argv
# 読み込まれている php.ini の場所
php-fpm8.3 -i 2>/dev/null | grep -i "Loaded Configuration File"
# サーバー上の pearcmd.php の有無
find / -name pearcmd.php -not -path '/proc/*' 2>/dev/null
php.ini を置かずに PHP の組み込み既定値で動いている環境(公式 Docker イメージをそのまま使っている場合など)では、register_argc_argv が On になっていることがあります。
4. すぐに更新できないときの一時的な緩和
検証待ちなどで即時更新できない場合の選択肢です。いずれも制限を強める方向の設定で、更新の代替にはなりません。できるだけ早く 2. の更新を実施してください。
PHP:register_argc_argv を Off にする
Web 経由のリクエストで register_argc_argv を使う WordPress サイトは通常ありません。RCE への経路を狭めるため Off にします。
; php.ini(PHP-FPM / mod_php が読み込むもの)
register_argc_argv = Off
# 設定後に PHP-FPM を再読み込み(サービス名は環境に合わせる)
sudo systemctl reload php8.3-fpm
使っていない PEAR を導入している場合は、パッケージ管理ツールから削除するのも有効です(他のアプリが PEAR を使っていないことを確認してから)。
Web サーバー:pagename に上位階層の指定が入ったリクエストを拒否する
国内外の解説では、固定ページを指定するクエリパラメータ pagename に、エンコードされた .. を含むアクセスが攻撃の典型として挙げられています。正規の固定ページ名に .. が入ることは無いため、拒否して困ることはまずありません。
nginx の場合(server ブロック内):
# pagename に ..(URLエンコード・二重エンコード含む)が入ったら 403
if ($arg_pagename ~* "(\.\.|%2e%2e|%252e%252e)") {
return 403;
}
Apache の場合(.htaccess の WordPress のルールより前に置く):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)pagename=[^&]*(\.\.|%2e%2e|%252e%252e) [NC]
RewriteRule ^ - [F]
</IfModule>
これは観測された典型パターンを止めるだけで、すべての経路を塞げる保証はありません。あくまで更新までのつなぎです。Cloudflare などの WAF を使っている場合は、ベンダーが CVE-2026-87902 向けのマネージドルールを出していないかも確認してください。
5. すでに踏まれていないかを確認する
RCE は、更新しても入られた後の痕跡は消えません。2026-09-22 以降に未修正だった期間がある場合は、次を確認します。
アクセスログ
# pagename に上位階層の指定が入ったアクセス(9/22 以降のログを対象に)
zgrep -iE "pagename=[^& ]*(\.\.|%2e%2e|%252e)" /var/log/nginx/access.log* \
| awk '{print $1}' | sort | uniq -c | sort -rn | head -20
# PEAR を狙ったアクセス
zgrep -iE "pearcmd|config-create" /var/log/nginx/access.log* | head -50
Apache の場合はログのパスを /var/log/apache2/access.log*(RHEL 系は /var/log/httpd/access_log*)に読み替えてください。ヒットしてもレスポンスが 403 / 404 なら失敗した試行の可能性が高いですが、200 を返しているものは要精査です。
不審な PHP ファイル
報告では、攻撃者が一時ディレクトリなどに PHP ファイルを書き込む動きが観測されています。
# 一時ディレクトリに PHP ファイルが無いか(本来ほぼ存在しない)
find /tmp /var/tmp -type f -name '*.php' -printf '%TY-%Tm-%Td %TH:%TM %p\n' 2>/dev/null
# 9/22 以降に WordPress 配下で作成・変更された PHP ファイル
find . -type f -name '*.php' -newermt '2026-09-22' -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
# uploads 配下の PHP ファイル(本来存在しないはず)
find wp-content/uploads -type f -name '*.php'
PHP-FPM でプライベート一時ディレクトリ(systemd の PrivateTmp)を使っている場合は、/tmp/systemd-private-* 配下も確認対象です。
コアの改ざん・アカウント・常駐
# コア・プラグインのファイル改ざん検査
wp core verify-checksums
wp plugin verify-checksums --all
# 身に覚えのない管理者アカウントが増えていないか
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
# 不審な常駐(mu-plugins / スケジュール実行)
ls -la wp-content/mu-plugins/
wp cron event list
痕跡が見つかった場合は、ファイルを消して終わりにせず、侵害前のバックアップからの復元と、管理者パスワード・DB パスワード・wp-config.php の認証用キー(salt)の変更までをセットで行ってください。
まとめ
- CVE-2026-87902 は WordPress 4.7.0〜7.1.1 のコアにある未認証の脆弱性で、CVSS v4.0 は 9.2。修正当日から攻撃が始まり、CISA の KEV にも追加済み
- まず
wp core versionで確認し、自分のブランチの修正版(最新は 7.1.2)以上へ更新する - 自動更新を止めている設定(
AUTOMATIC_UPDATER_DISABLED/WP_AUTO_UPDATE_CORE)が無いか点検し、セキュリティ修正は自動で入る状態に戻す - 更新までのつなぎとして
register_argc_argv = Offと、pagenameの上位階層指定の拒否が使える - 9/22 以降に未修正の期間があったサイトは、アクセスログ・一時ディレクトリの PHP ファイル・管理者アカウントを確認する
関連記事
本記事のような更新漏れ・設定の抜けは、Web サイトを 9 つの守りでまるごと守るサイトドックでまとめて対策できます → https://sitedock.jp