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攻击, 多线程, 漏洞披露, 蓝队分析, 越权漏洞