2026.08.12
※この記事は2026年08月12日時点の情報をもとに作成されました。
2026年7月17日、WordPress本体に深刻な脆弱性が公表されました。通称「wp2shell」と呼ばれるもので、プラグインを一切入れていない標準構成のサイトでも成立します。すでに実際の攻撃が確認されており、放置は危険です。
この記事では、対象バージョンの確認方法、攻撃の仕組み、そして「更新する」だけで終わらせないための確認手順を、制作・保守を担当する方向けに整理します。
まず自分のサイトが該当するかを確認してください。危険度はバージョンによって異なります。
| バージョン | 影響 |
|---|---|
| 7.0.0 〜 7.0.1 | リモートコード実行(RCE)が成立 |
| 6.9.0 〜 6.9.4 | リモートコード実行(RCE)が成立 |
| 6.8.0 〜 6.8.5 | SQLインジェクションのみ(RCEは不成立) |
修正版は 7.0.2 / 6.9.5 / 6.8.6 以降です。使用中のバージョンは、管理画面の「ダッシュボード」→「更新」、または「ツール」→「サイトヘルス」→「情報」→「WordPress」で確認できます。
WordPress.org は自動更新システムを通じた強制配信も行っていますが、自動更新を明示的に無効化しているサイトに適用されたかは公表されていません。「自動更新にしてあるから大丈夫」と考えず、実際のバージョン番号を目視で確認してください。
wp2shell は、2つの脆弱性を連鎖させる攻撃です。
WordPressには複数のAPIリクエストをまとめて処理する /wp-json/batch/v1 というエンドポイントがあります。ここで検証に失敗したリクエストがあると、配列の添字がずれて別の処理が実行されるという不具合がありました。結果として、本来必要な権限チェックが迂回されます。
投稿一覧の絞り込みに使う author__not_in というパラメータが、配列ではない値を渡されたときに検証を素通りし、そのままSQL文に連結される不具合です。
①で権限チェックを回避し、②でデータベースを操作できるため、ログインしていない第三者が、管理者権限の取得からコード実行まで到達できます。攻撃にはログイン情報もプラグインも必要ありません。URLを知られている=攻撃対象、という状態です。
公開直後は「悪用の確認なし」とする報告もありましたが、7月21日に米CISAが「悪用が確認された脆弱性カタログ(KEV)」へ両CVEを登録しました。観測されている内容は次のとおりです。
国内でも、7月22日にIPAが「重要なセキュリティ情報」に掲載、7月23日にJPCERT/CCがWeekly Reportで取り上げています。
7.0.2 / 6.9.5 / 6.8.6 以降へ更新します。メジャーバージョンをまたぐ更新に不安がある場合でも、自分の系列の修正版(6.9系なら6.9.5)へ上げれば対処できます。大きな移行を待つ必要はありません。
検証が必要ですぐ更新できない場合、攻撃の入口を塞ぐ方法があります。
/wp-json/batch/v1 と ?rest_route=/batch/v1 へのアクセスを遮断するrest_pre_dispatch フィルタで、未認証の batch/v1 へのリクエストを拒否するただしこれは時間を稼ぐための措置です。根本対応は更新です。
更新はこれ以降の攻撃を防ぎますが、更新前に侵入されていた場合、その痕跡は残ったままです。次を確認してください。
POST /wp-json/batch/v1、POST /?rest_route=/batch/v1 へのリクエスト。特にステータス207の応答wp-content/uploads 内の .php ファイル:正常な運用では存在しませんログの保存期間はサーバーによって数週間程度です。確認するなら早い方が良い理由がここにあります。
今回のように本体側の脆弱性は、プラグインを厳選していても、更新を欠かさなくても、公表から更新までの間は無防備になります。防ぎきれない前提で、戻せる状態を用意しておくことが最後の砦になります。
3番目が抜けている現場は多いです。バックアップは取得できていても、いざ戻そうとするとファイル欠損や容量制限で失敗する、という事態は珍しくありません。検証環境で一度復元してみるだけで、この不確実性はなくなります。
改ざんは気づくまでに時間がかかります。1世代だけしか保持していないと、侵害後の状態で上書きされたバックアップしか残らないことがあります。最低でも数世代、可能なら1か月分は保持してください。
当社で保守している数十サイトに対して実際に行った対応を、順を追って記載します。制作会社の方が自社の管理サイトに対応する際の参考になれば幸いです。
最初にやるべきは、どのサイトが対象バージョンなのかの一覧化です。管理サイトが数十件あると、1件ずつ管理画面を開くだけで半日が消えます。当社は保守対象サイトのWordPressバージョンを台帳で一元管理しており、対象バージョンのサイトを即座に抽出できる状態にしていました。この一覧化の速さが、初動の速さをそのまま決めます。
更新は検証を挟むため、全サイトに行き渡るまで時間がかかります。その間を無防備にしないため、未ログイン状態からのバッチエンドポイントへのアクセスを拒否する mu-plugin を作成し、73サイトへ一斉配布しました。rest_pre_dispatch フィルタで、未ログインの /batch/v1 宛リクエストを403で返す実装です。
実装で意識した点が2つあります。
ここで実際に問題が見つかりました。初版は対象ルートの判定に単純な文字列一致を使っていましたが、WordPressのルート照合は大文字小文字を区別しません。つまり /wp-json/Batch/v1 のような表記でリクエストされると、判定を素通りして本来のハンドラに到達してしまいます。
大文字小文字を無視する正規表現による判定に修正し、再配布しました。緩和策は「入れた」だけでは不十分で、回避経路がないかまで確認する必要があるという実例です。
副次的に起きた問題として、配布した防御用ファイル自体が、日次のマルウェアスキャンで「不審なファイル」として検出されました。mu-plugins に見慣れないPHPファイルが突然増えるため、検知側から見れば改ざんと区別がつきません。
自作の防御ファイルを検査対象から除外する設定を入れて解消しましたが、緊急対応でファイルを配布するときは、監視側の設定も同時に見直す必要があるということです。除外を入れないまま放置すると、本物の検出が埋もれます。
調査の結果、侵入を受けていたサイトについては、3件をバックアップファイルから復旧しました。不正なファイルを個別に削除する方法は、バックドアの取りこぼしが起きます。侵入経路を特定したうえで、侵害前の状態に戻し、修正版へ更新してから公開に戻す手順を取りました。
復旧できたのは、バックアップが世代で残っていたからです。1世代しか保持していなければ、侵害後の状態で上書きされたものしか残らず、戻す先がありませんでした。
あわせて、全サイトのバックアップが最新かを点検しました。この点検で、一部のサイトでバックアップの取得が止まっていることが判明しました。平時は誰も気づきませんが、復旧が必要になった瞬間に致命的になります。脆弱性対応のたびに復元手段を点検する運用にしています。
管理サイトが多く手が回らない、確認の仕方が分からない、という場合はご相談ください。制作会社様からの保守・調査のご依頼を承っています。
弊社では上記ブログ内容にある修正・カスタマイズのご依頼も承っております。
ご自身で行ってみて上手くいかない場合などこちらよりお気軽にご相談ください。