
CVE-2026-16540 — Simply Schedule Appointments < 1.6.12.6 كشف بيانات المواعيد والحذف الجماعي دون مصادقة
purge| الحقل | التفاصيل |
|---|---|
| CVE | CVE-2026-16540 |
| البرنامج المساعد | 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 (تفويض غير صحيح) |
| OWASP | A5: التحكم في الوصول المعطوب |
| WPVDB | c3829294-c388-4151-9e25-a3eac7b1f1c6 |
| الباحث | Suleyman Huseynov (@huseyn0vs__) |
| تاريخ الإفصاح | 2026-07-22 |
نقطة نهاية REST GET /wp-json/ssa/v1/appointments/purge في Simply Schedule Appointments تطبّق فحص تفويض (get_items_permissions_check) يتحقق من id_token الذي يثبت ملكية موعد واحد فقط. ومع ذلك، يتجاهل المعالج (purge_appointments()) تمامًا الموعد الذي ينتمي إليه الرمز ويعمل بدلاً من ذلك على جميع المواعيد على مستوى الموقع التي تطابق الشروط المقدَّمة.
يستطيع المهاجم غير المصادق عليه الذي يحجز أي موعد واحد عبر نموذج الحجز العام الحصول على id_token. وباستخدام هذا الرمز، يمكن للمهاجم:
يمتد الحذف عبر 6 جداول قاعدة بيانات مرتبطة في معاملات ملتزمة، دون أي وظيفة تراجع أصلية.
الملف: includes/class-appointment-model.php
بوابة الصلاحيات والمعالج يعملان على نطاقات مختلفة تمامًا:
// 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
}
// ...
}
المعالج — يتجاهل موعد الرمز ويعمل على مستوى الموقع:
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 هو HMAC-MD5 مشتق من id و date_created لموعد واحد. امتلاك هذا الرمز يثبت فقط أن المتصل حجز موعدًا واحدًا محددًا — ولا يمنح أي صلاحية على مستوى الموقع على الإطلاق.
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=<appointment_id>
&token=<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)
سيتم نشر إثبات المفهوم في 2026-08-05 بعد انتهاء فترة حظر الإفصاح المنسق.
انظر دليل poc/ بعد تاريخ انتهاء الحظر.
| السيناريو | النتيجة |
|---|---|
| كشف البيانات | أسماء، رسائل بريد إلكتروني، أرقام هواتف، وتفاصيل مواعيد جميع العملاء |
| الحذف الجماعي (المدفوع) | تدمير جميع المواعيد التاريخية/المستقبلية نهائيًا عبر 6 جداول |
| لا يوجد مسار استرداد | يتطلب استعادة كاملة من نسخة احتياطية لقاعدة البيانات |
| التاريخ | الحدث |
|---|---|
| 2026-07-10 | اكتشاف الثغرة |
| 2026-07-10 | إرسالها إلى WPScan |
| 2026-07-22 | تعيين CVE-2026-16540 |
| 2026-07-22 |
| إفصاح عام على WPScan |
| 2026-08-05 | نشر إثبات المفهوم |