huseyn0vs/CVE-2026-16540-SimplyScheduleAppointments
GitHub: huseyn0vs/CVE-2026-16540-SimplyScheduleAppointments
针对 WordPress Simply Schedule Appointments 插件未授权预约数据泄露与批量删除漏洞(CVE-2026-16540)的概念验证与技术分析项目。
Stars: 0 | Forks: 0
# CVE-2026-16540 — Simply Schedule Appointments < 1.6.12.6
## 通过 `purge` 端点进行的未授权预约数据泄露与批量删除
| 字段 | 详情 |
|-------|---------|
| **CVE** | CVE-2026-16540 |
| **插件** | [Simply Schedule Appointments](https://wordpress.org/plugins/simply-schedule-appointments/) |
| **受影响版本** | < 1.6.12.6 |
| **修复版本** | 1.6.12.6 |
| **活跃安装量** | ~70,000 |
| **CVSS 3.1** | 6.5 (中危) — `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N` |
| **CWE** | CWE-863 (Incorrect Authorization) |
| **OWASP** | A5: Broken Access Control |
| **WPVDB** | [c3829294-c388-4151-9e25-a3eac7b1f1c6](https://wpscan.com/vulnerability/c3829294-c388-4151-9e25-a3eac7b1f1c6) |
| **研究员** | Suleyman Huseynov ([@huseyn0vs__](https://twitter.com/huseyn0vs__)) |
| **披露日期** | 2026-07-22 |
## 摘要
Simply Schedule Appointments 中的 `GET /wp-json/ssa/v1/appointments/purge` REST 端点应用了一个授权检查 (`get_items_permissions_check`),该检查用于验证证明拥有**单个**预约的 `id_token`。然而,处理程序 (`purge_appointments()`) 完全忽略了该 token 所属的预约,而是针对全站点范围内匹配所提供条件的**所有**预约进行操作。
通过公共预约表单预订任意单个预约的未授权攻击者会收到一个 `id_token`。使用该 token,攻击者可以:
1. **检索**全站点所有预约的**个人数据**(姓名、电子邮件、电话号码、预约详情)
2. **永久删除**所有过去、已取消或未来的预约(仅限高级版本支持删除)
删除操作会在已提交的事务中级联影响到 6 个依赖的数据库表,且没有原生的撤销功能。
## 根本原因分析
**文件:** `includes/class-appointment-model.php`
### 错误的资源授权 (CWE-863)
权限网关和处理程序在完全不同的作用域上运行:
```
// Route registration
register_rest_route( $namespace, '/' . $base . '/purge', array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'purge_appointments' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
),
) );
```
**权限检查** — 通过 `id_token` 验证单个预约的所有权:
```
public function get_items_permissions_check( $request ) {
// ...
if ( true === $this->id_token_permissions_check( $request ) ) {
return true; // grants access if caller proves ownership of one appointment
}
// ...
}
```
**处理程序** — 忽略 token 的关联预约并在全站点范围内进行操作:
```
public function purge_appointments( WP_REST_Request $request ) {
$params = $request->get_params();
// No customer_id or appointment_id scoping — deletes ALL matching appointments
if ( isset( $params['purge_past_appointments'] ) && 'true' === $params['purge_past_appointments'] ) {
$conditions[] = $wpdb->prepare( 'end_date < %s', $date_modified_max->format( 'Y-m-d' ) );
}
$sql = 'SELECT * FROM ' . $this->get_table_name()
. ' WHERE ' . implode( ' OR ', $conditions )
. ' ORDER BY id ASC LIMIT 5000';
$list = $wpdb->get_results( $sql, ARRAY_A );
// Cascade-deletes across 6 tables in committed transactions
}
```
`id_token` 是根据单个预约的 `id` 和 `date_created` 派生出的 HMAC-MD5。拥有此 token 仅能证明调用者预订了某一个特定的预约 —— 它绝对不授予任何全站点的权限。
## 攻击链
```
1. Attacker visits the booking page and books any free appointment
→ receives confirmation email containing: appointment_id + id_token
2. GET /wp-json/ssa/v1/appointments/purge
?id=
&token=
&purge_past_appointments=true
3. Permission check passes (valid token for attacker's own appointment)
4. Handler selects ALL past appointments site-wide → returns PII in response
→ permanently deletes them across 6 tables (on premium editions)
```
## 概念验证
请查看 embargo 日期之后的 [`poc/`](./poc/) 目录。
## 影响
| 场景 | 结果 |
|----------|--------|
| 数据泄露 | 所有客户的姓名、电子邮件、电话号码和预约详情 |
| 批量删除(高级版) | 跨 6 个表永久销毁所有历史/未来预约 |
| 无恢复途径 | 需要进行完整的数据库备份恢复 |
## 修复建议
修复方案应将 `purge_appointments()` 处理程序的作用域限定为仅对属于已验证 token 所有者的预约进行操作,或者将该端点限制为仅管理员可用:
```
// Option 1: Restrict to admins only
'permission_callback' => function( $request ) {
return current_user_can( 'ssa_manage_site_settings' );
}
// Option 2: Scope deletion to token owner's appointment only
$customer_id = $this->get_customer_id_from_token( $request );
$conditions[] = $wpdb->prepare( 'customer_id = %d', $customer_id );
```
**已在 1.6.12.6 版本中修复。**
## 披露时间线
| 日期 | 事件 |
|------|-------|
| 2026-07-?? | 发现漏洞 |
| 2026-07-22 | 提交至 WPScan |
| 2026-07-22 | 分配 CVE-2026-16540 |
| 2026-07-22 | 在 WPScan 上公开披露 |
| 2026-08-05 | 发布 PoC |
## 参考
- [WPScan 安全通告](https://wpscan.com/vulnerability/c3829294-c388-4151-9e25-a3eac7b1f1c6)
- [WordPress 插件页面](https://wordpress.org/plugins/simply-schedule-appointments/)
- [CWE-863: Incorrect Authorization](https://cwe.mitre.org/data/definitions/863.html)
- [OWASP A5: Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/)
标签:CISA项目, Web安全, WordPress插件, XXE攻击, 多线程, 漏洞披露, 蓝队分析, 越权漏洞