wp2shell(CVE-2026-63030 / CVE-2026-60137)とは。WordPress の事前認証 RCE で確認すること

Severity
Critical
Status
要確認
CVE
CVE-2026-63030, CVE-2026-60137
Affected
WordPress 6.9.0-6.9.4, WordPress 7.0.0-7.0.1, WordPress 6.8.0-6.8.5

WordPress を 6.9 系か 7.0 系で動かしているなら、今すぐ 6.9.5 / 7.0.2 に上げてください。

2026年7月17日(米国時間の金曜日)、日本時間だと7月18日に出た WordPress のセキュリティリリースの話です。

通称は wp2shell。

CVE-2026-63030 と CVE-2026-60137 の2件を連鎖させると、ログイン不要でサイトを乗っ取られます。

プラグインは関係ありません。素の WordPress で成立します。

しかも公開から数時間で PoC が出回り、週末には実際の攻撃が観測されました。

過去に扱った NGINX Rift のときは「見出しほど全台アウトではない」という温度感の調整が必要でしたが、今回は違います。

対象バージョンなら、問答無用で更新するやつです。

概要

項目内容
CVECVE-2026-63030、CVE-2026-60137
通称wp2shell
種別REST API のルート混同 + SQL インジェクション
影響箇所/wp-json/batch/v1?rest_route=/batch/v1)、WP_Queryauthor__not_in
影響範囲WordPress 6.9.0〜6.9.4、7.0.0〜7.0.1(RCE)、6.8.0〜6.8.5(SQLi のみ)
修正版7.0.2、6.9.5、6.8.6、7.1 beta2
公開日2026年7月17日(米国時間)
報告者Adam Kues(Assetnote / Searchlight Cyber)、TF1T、dtro、haongo

重大度の書き方は、出典によって割れています。

wordpress.org のリリースノートは「critical 1件と high 1件」という書き方をしていて、どちらがどちらかは明示していません。SecurityWeek は CVE-2026-63030 を critical の任意コード実行、CVE-2026-60137 を high の SQLi として扱っています。一方 VulnCheck は逆で、CVE-2026-60137 を critical の SQLi、CVE-2026-63030 を high のルート混同としています。Rapid7 は CVE-2026-63030 の CVSS を 7.5、GitHub Security Advisory 上の分類は Critical と記載しています。

どちらに寄せても、やることは変わりません。

連鎖した結果が事前認証 RCE である、という点はすべての出典で一致しています。

何が起きるのか

2つの脆弱性が噛み合うと、認証を通らずに管理者になれます。

まず CVE-2026-63030。REST API の batch エンドポイント /wp-json/batch/v1 におけるルート混同で、実質的に認証バイパスとして機能します。この batch ルートは WordPress 6.9 で追加されたもので、6.8 以前には存在しません。

次に CVE-2026-60137。WP_Queryauthor__not_in パラメータにある SQL インジェクションです。こちらは本来、認証済みでないと触れない場所にあります。

攻撃はこの順で進みます。

  1. CVE-2026-63030 で認証制限を回避する
  2. CVE-2026-60137 の SQL インジェクションで、新しい管理者ユーザーをデータベースに作る
  3. 管理画面にログインし、プラグインを装った webshell をアップロードする

パスワードハッシュの解読は必要ありません。ハッシュを割るのではなく、自分のアカウントを増やすだけなので。

Rapid7 は「永続オブジェクトキャッシュが無い場合に顕在化する」という条件にも触れています。ただ、Redis や Memcached を入れているから安全、と読める話ではないです。キャッシュ構成を理由に更新を先送りする材料にはしないほうがいいと考えています。

悪用の状況

時系列で並べるとこうなります。

  • 2026年7月17日、修正版と GitHub Security Advisory が公開される。Searchlight Cyber は悪用防止のため技術詳細を伏せていた
  • 同日の米国東部時間 17時45分時点で、Rapid7 は実際の悪用を未確認としつつ、「オープンソースであることと AI の存在から、短期間で PoC が公開されるだろう」と評価していた
  • 公開から数時間後、GitHub に PoC が出現
  • 7月19日、VulnCheck が2ダース以上のユニークな PoC を確認
  • 週末にかけて Hexastrike がハニーポットで悪用試行を検知し、複数の実インシデント対応に入る。Patchstack と watchTowr も実環境での悪用を確認。Cloudflare が検知ルールを展開
  • 7月20日、活発な悪用が確認済み。攻撃者は侵害したサーバーに永続的な webshell を設置している

Rapid7 の予想が、ほぼそのまま2日で現実になった形です。

WordPress は世界で5億以上のサイトが動いているとされていて、攻撃側から見れば的が多すぎます。金曜に出たパッチが週末を挟むという、いちばん嫌な曜日回りでもありました。

Sponsored

影響を受けるか確認する

見るのはバージョンだけです。設定条件のようなものはありません。

  • 6.9.0〜6.9.4 は RCE チェーンの影響を受ける。最優先で更新
  • 7.0.0〜7.0.1 も同じ
  • 6.8.0〜6.8.5 は batch ルートが無いので RCE までは到達しないが、SQLi の影響は受ける。6.8.6 へ
  • 6.8 より前は影響なし

バージョンの確認方法はいくつかあります。管理画面のダッシュボードを開けば下部に出ますし、ファイルを直接見るなら wp-includes/version.php$wp_version です。

WP-CLI が入っているなら早いです。

wp core version

複数サイトを持っている人ほど、ここで漏れます。テスト用に立てて放置しているサブドメインとか、staging とか。動いている WordPress を全部洗い出すところからやってください。

更新する

修正版は 7.0.2、6.9.5、6.8.6、そして 7.1 beta2 です。

深刻度が高いため、WordPress.org チームが自動更新システム経由で強制更新を有効化しています。自動更新を切っていない環境なら、すでに上がっている可能性が高いです。

とはいえ、「かかったはず」で終わらせないほうがいいです。

自動更新はファイル権限やディスク容量で普通に失敗します。更新後のバージョンは自分の目で確認してください。

wp core update
wp core version

管理画面から入れるなら、ダッシュボードの「更新」から「今すぐ更新」でも同じです。

すぐ更新できない場合

WAF 側で batch エンドポイントを塞ぐ、という緩和策が各社から出ています。

  • /wp-json/batch/v1 への未認証アクセスをブロックする
  • ?rest_route=/batch/v1 の形式も併せてブロックする(こちらを忘れると素通りします)
  • 匿名の REST API アクセスを制限するプラグインを入れる

Cloudflare の保護は全プランで利用できるとアナウンスされています。

ただ、これらは全部あくまで暫定です。Rapid7 にいたっては「回避策は推奨しない、直ちにパッチを当てろ」という立場を取っています。

更新できない理由がテーマやプラグインの互換性なら、その互換性を確認している数時間のあいだも攻撃は飛んできます。先に WAF で塞いでから確認する、という順序にしたほうがいいです。

侵害されていないか確認する

ここが本題かもしれません。

7月18日から今日までのあいだサイトを公開していたなら、更新して終わりにはできません。パッチが出る前に入られていた場合、更新してもバックドアは残ります。

アクセスログで見るところを挙げます。

Wiz は、batch エンドポイントへのリクエストに対する HTTP 207 または 200(Multi-Status)のレスポンスを「悪用成功の比較的高精度な指標」としています。

grep -E 'batch/v1' /var/log/nginx/access.log* | grep -E ' (207|200) '

公開ツールのシグネチャも分かりやすいです。User-Agent に wp2shellrezwp2shell を含むリクエストがあれば、狙われたのは確実です。

Sponsored

grep -iE 'wp2shell|rezwp2shell' /var/log/nginx/access.log*

侵害後の挙動として見るべきものは次のあたり。

  • POST /wp-admin/update.php?action=upload-plugin(不正プラグインのアップロード)
  • /wp-admin/plugin-install.php?tab=upload へのアクセス
  • /wp-json/wp/v2/users?context=edit(ユーザー列挙)
  • admin-ajax.php?template=../../../wp-config 形式の LFI 試行
  • /wp-admin/ への HTTP 200 での成功アクセス

ユーザー列挙のところ、以前に書いた記事とつながります。

WordPress のユーザ API を閉じておく話を2025年に書いたのですが、今回の入口も結局 REST API でした。REST API は WordPress の攻撃面としてずっと同じ場所にあり続けている、ということかなと。

サイト側では、管理者ユーザーの一覧を必ず見てください。

wp user list --role=administrator

身に覚えのないアカウントがあれば、それが作られたやつです。

ファイル側も見ます。設置される webshell は、数行のワンライナーから、正規プラグインを装った 150KB 規模の攻撃フレームワークまで幅があります。hex エンコードや gzip 圧縮で難読化されているので、目視で「怪しいコード」を探す方針だと見落とします。

素直に更新日時で拾ったほうが早いです。

find wp-content/ -name '*.php' -newermt '2026-07-17' -ls

侵害が疑わしいときにやること

見慣れないファイルや管理者アカウントが出てきたら、そのサイトは侵害済みとして扱ってください。

該当ファイルを消して終わり、にはしないほうがいいです。管理者権限を取られた後の環境は、データベースにも wp-config.php にもテーマの functions.php にも仕込める状態だったわけで、削除漏れが1つでもあれば元通りになります。

やることの並びとしては、こうなります。

  1. 先にログとファイルを保全する(消す前にコピーを取る)
  2. サイトを一旦閉じるか、WAF で管理画面へのアクセスを絞る
  3. WordPress、テーマ、プラグインをすべてクリーンな配布物で入れ直す
  4. 全ユーザーのパスワードとデータベース認証情報をローテーションする
  5. wp-config.php の認証用ユニークキーを再生成する
  6. 侵害前のバックアップがあるなら、そこまで戻したうえで更新する

今回やらないほうがいい判断

「うちは小さいサイトだから狙われない」は、今回に限っては通用しません。今は PoC を持った側が手当たり次第に投げている段階で、選別の基準はバージョンだけです。サイトの規模も知名度も見られていません。

「自動更新に任せているから確認不要」も雑です。強制更新がかかったこと自体は事実ですが、それが自分のサイトで成功したかどうかは別の話。バージョン表示を見るだけなので、確認してください。

逆に、6.8 未満で止まっている古いサイトについて「今回は影響なし」と分かったからといって、そのまま放置していい理由にもなりません。今回の対象外というだけです。

そもそも WordPress を持ち続けるコストの話でもあるのですが、それはまた別の記事で書きます。

参考リンク