mr-r3b00t/wp2shell
GitHub: mr-r3b00t/wp2shell
针对 WordPress batch/v1 REST API 盲注 SQLi 漏洞的完整攻击链验证与 DFIR 事件响应工具包。
Stars: 2 | Forks: 0
# wp2shell 安全验证与 DFIR 工具包
目标:WordPress 核心 `batch/v1` REST **路由混淆 → `author__not_in` 盲注 SQLi**。
(无需身份验证)。受影响版本 **6.9.0–6.9.4, 7.0.0–7.0.1**;已修复版本 **6.9.5 / 7.0.2**。
完整攻击链包含:离线哈希破解 → 认证后的插件上传 → webshell。
## 内容清单
| 文件 | 用途 |
|------|---------|
| `ATTACKER_PACKETS.md` | 对发送的确切请求添加了注释的网络层抓包视图 |
| `wp2shell_check.py` | 非破坏性 PoC:版本检测 / 检查 / 验证 / 提取 |
| `IR_RUNBOOK.md` | 事件响应手册 (检测→保留→遏制→根除→恢复) |
| `detect/wp2shell.suricata.rules` | IDS/IPS 特征规则 (URI + body) |
| `detect/wp2shell.sigma.yml` | SIEM 检测规则 (webserver/WAF 日志) |
| `detect/hunt_logs.py` | 离线日志狩猎:SQLi + webshell 访问 + 时间分析 |
| `detect/scan_webshells.sh` | 针对 WP webroot 的文件系统 webshell 扫描器 |
| `detect/webshells.yar` | 用于 PHP webshell / 后门的 YARA 规则 |
| `detect/wp_ioc_scan.sh` | 全面的 IOC 扫描 → HTML **和/或** JSON 报告 (24 项检查) |
## 全面 IOC 扫描 (`wp_ioc_scan.sh`)
文件系统 + 核心完整性 + 配置 + 数据库 + 访问日志检查,每项均带有深入细节的 PASS/FAIL/WARN/INFO 状态。只读模式;遇到任何 FAIL 均以非零状态退出 (可用于 CI/cron)。
```
# HTML 报告
./wp_ioc_scan.sh --webroot /path/to/wp --access-log access.log --output report.html
# 用于 SIEM 的 JSON (无 HTML)
./wp_ioc_scan.sh --no-html --json report.json
# 同时生成两者
./wp_ioc_scan.sh --output report.html --json report.json
```
JSON 结构:`{ meta{host,webroot,wp_version,access_log,generated},
summary{pass,fail,warn,info,total}, findings[{status,title,summary,details}] }`。
## webshell 检测与响应 (与实验室环境配合)
模拟真实的后渗透过程,随后进行检测和清理。**仅供实验室使用。**
```
# 植入 (3 个 vectors: malicious plugin, PHP-in-uploads, theme-file infection)
docker compose exec -T wordpress bash /tmp/plant_webshell.sh
# 在磁盘中检测
docker compose exec -T wordpress bash /tmp/scan_webshells.sh
yara -r detect/webshells.yar /wp-content
# 在日志中检测 (在 shell 被使用后)
docker compose logs --no-log-prefix wordpress | python3 detect/hunt_logs.py -
# 响应
docker compose exec -T wordpress bash /tmp/eradicate_webshell.sh
```
内置的关键 IR 经验教训:**即使磁盘上的文件已被清理,opcache 仍会从内存中提供恶意字节码** —— 恢复一个具有较早 mtime 的文件并不会使其失效。根除时必须更新 mtime 或重启 PHP (`docker compose
restart wordpress`)。参见 `IR_RUNBOOK.md`。
## PoC (仅限授权目标) — 需要 Python 3,仅使用标准库
```
python3 wp2shell_check.py version http://TARGET # fingerprint
python3 wp2shell_check.py check http://TARGET --sleep 3 # confirm (time-based)
python3 wp2shell_check.py prove http://TARGET --expr "@@version" # prove read
python3 wp2shell_check.py dump http://TARGET --rows 1 # extract credentials
python3 wp2shell_check.py check http://TARGET -A chrome # spoof UA past a WAF
```
`-A/--user-agent` (适用于所有子命令) 可接受预设值 (`chrome`/`firefox`/`safari`/
`default`) 或字面量 UA。默认 UA 会表明该工具的身份;只有在客户 WAF 在授权测试期间阻止了默认 UA 时,才应覆盖它。请注意,此处的 DFIR 检测依赖于 batch/v1 的 **body/行为**,而不是 UA —— 因此伪造的 User-Agent **并不能**规避检测 (这正是为什么基于 body 的特征规则至关重要的原因)。
如果存在漏洞 `check` 将退出并返回状态码 0,否则返回 1。`dump` 会进行盲提取以获取 `wp_users`
(登录名 / 密码哈希 / 邮箱) —— 这是渗透测试报告中所需的账户接管影响证明,并且它会报告其观察到的哈希格式。请注意,WP 6.8+ 存储
`$wp$2y$` **bcrypt** 哈希 (基于 base64(sha384(pw)) 的 bcrypt),因此传统的
`hashcat -m 400` (phpass) **不**适用于 7.0.x 目标 —— 请使用你的 hashcat 构建版本中的 WordPress-bcrypt 模式。插件上传 webshell 是后续步骤,包含在公开工具中。
### 提取模式 (`prove` / `dump`)
- `--mode content` **(默认,快速)** —— 从嵌套 batch 响应中被错误分发的 posts 数组中读取布尔值 (`responses[1].body.responses[1].body`):
TRUE 保持 posts 可见,FALSE 将其隐藏。每次测试约 1 个快速请求,无需 sleep,
因此可以在几秒钟内提取完整的哈希。在使用前会自动校准 (`1=1` 对比 `1=2`)。
- `--mode time` **(后备)** —— `IF(cond, SLEEP(n), 0)`,根据延迟判断结果。
在以下情况使用:响应被缓存/统一、WAF 对 body 进行了标准化,或者站点没有已发布的 posts (在这种情况下 content 预言机无法区分 TRUE/FALSE)。
两种模式都使用相同的二分搜索提取器 (已验证:仅需根据布尔响应即可重构包含 `$ | . /` 的字符串和整数)。`--rows 1` 仅通过 admin 行即可证明影响。
## DFIR
```
python3 detect/hunt_logs.py /var/log/nginx/access.log
cat modsec_audit.log | python3 detect/hunt_logs.py - # body-bearing capture
```
### 攻陷 / 攻击指标 (IOC)
- 来自不受信任 IP 的 `POST /wp-json/batch/v1/` 或 `POST /?rest_route=/batch/v1/`
- 请求 body 包含 `"///"` (去同步 primer) **且**包含 `author_exclude`
- `author_exclude` 值包含 `)`, `SLEEP(`, `BENCHMARK(`, `-- -`, `OR`, `AND`
- 嵌套的 `requests` 数组 (子请求 `body` 内的 `requests` 键)
- 同一 endpoint 的 POST 请求集群,响应时间约为 N 秒的倍数
(基于时间的盲注);大量请求 + 长运行时间 = 正在进行提取
- 后续动作:同一 IP 成功访问 `/wp-login.php`,随后
`POST /wp-admin/update.php?action=upload-plugin`,接着 GET 访问新的
`/wp-content/plugins//.php?t=...&c=...`
### 分诊优先级
1. 主机是否在受影响范围内?(`wp2shell_check.py version`)
2. 日志中是否存在带有上述 body/时间 IOC 的 batch/v1 流量?
3. 如果是 → 假定 `wp_users` 哈希已外泄:强制重置管理员密码,
轮换 salts (`wp-config.php` keys),审计是否存在恶意插件/管理员用户。
4. 打补丁至 7.0.2 / 6.9.5;临时方案:在 WAF/edge 层拦截 `/wp-json/batch/v1` + `rest_route=/batch/v1`。
## 注意事项
- 基于 body 的检测要求日志源能够捕获请求 body
(WAF、mod_security 审计日志、反向代理)。标准的访问日志只能看到
URI —— 对于固定链接 `POST /wp-json/batch/v1/` 形式,payload 位于 body 中,不会出现在那里;请依赖 IDS body 规则或时间分析。
- `rest_route=/batch/v1` 形式仍然会在访问日志中显示 endpoint (并且对于通过 GET 走私的变体,还会显示查询字符串)。
- 基于 7.0.1→7.0.2 代码差异 + 公开 PoC 进行分析;在最终确定报告之前,请交叉核对指定的 CVE/CVSS。
标签:CISA项目, IOC扫描, Metaprompt, PoC, WordPress, 后端开发, 安全检测规则, 库, 应急响应, 应用安全, 数字取证, 暴力破解, 自动化脚本, 请求拦截