
CVE-2026-16540 — Simply Schedule Appointments < 1.6.12.6 Nicht authentifizierte Offenlegung von Termindaten und Massenlöschung
purge-Endpunkt| Feld | Details |
|---|---|
| CVE | CVE-2026-16540 |
| Plugin | Simply Schedule Appointments |
| Betroffene Versionen | < 1.6.12.6 |
| Behoben in | 1.6.12.6 |
| Aktive Installationen | ~70.000 |
| CVSS 3.1 | 6.5 (Medium) — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N |
| CWE | CWE-863 (Falsche Autorisierung) |
| OWASP | A5: Fehlerhafte Zugriffskontrolle |
| WPVDB | c3829294-c388-4151-9e25-a3eac7b1f1c6 |
| Forscher | Suleyman Huseynov (@huseyn0vs__) |
| Offengelegt | 2026-07-22 |
Der REST-Endpunkt GET /wp-json/ssa/v1/appointments/purge in Simply Schedule Appointments wendet eine Autorisierungsprüfung (get_items_permissions_check) an, die ein id_token validiert, das den Besitz eines einzelnen Termins nachweist. Der Handler (purge_appointments()) ignoriert jedoch vollständig, zu welchem Termin der Token gehört, und operiert stattdessen auf allen Terminen der gesamten Website, die den angegebenen Bedingungen entsprechen.
Ein nicht authentifizierter Angreifer, der über das öffentliche Buchungsformular einen einzelnen Termin bucht, erhält ein id_token. Mit diesem Token kann der Angreifer:
Die Löschung erstreckt sich kaskadenartig über 6 abhängige Datenbanktabellen in festgeschriebenen Transaktionen, ohne native Rückgängig-Funktion.
Datei: includes/class-appointment-model.php
Die Berechtigungsprüfung und der Handler arbeiten in vollständig unterschiedlichen Bereichen:
// Routenregistrierung
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' ),
),
) );
Berechtigungsprüfung – validiert den Besitz EINES Termins über id_token:
public function get_items_permissions_check( $request ) {
// ...
if ( true === $this->id_token_permissions_check( $request ) ) {
return true; // gewährt Zugriff, wenn der Aufrufer den Besitz eines Termins nachweist
}
// ...
}
Handler – ignoriert den Termin des Tokens und operiert websiteweit:
public function purge_appointments( WP_REST_Request $request ) {
$params = $request->get_params();
// Keine Eingrenzung auf customer_id oder appointment_id – löscht ALLE passenden Termine
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 );
// Kaskadenlöschung über 6 Tabellen in festgeschriebenen Transaktionen
}
Das id_token ist ein HMAC-MD5, der aus der id und date_created eines einzelnen Termins abgeleitet wird. Der Besitz dieses Tokens beweist lediglich, dass der Aufrufer einen bestimmten Termin gebucht hat – es verleiht keinerlei websiteweite Berechtigung.
1. Angreifer besucht die Buchungsseite und bucht einen beliebigen kostenlosen Termin
→ erhält Bestätigungs-E-Mail mit: appointment_id + id_token
2. GET /wp-json/ssa/v1/appointments/purge
?id=<appointment_id>
&token=<id_token>
&purge_past_appointments=true
3. Berechtigungsprüfung besteht (gültiger Token für den eigenen Termin des Angreifers)
4. Handler wählt ALLE vergangenen Termine websiteweit aus → gibt PII in der Antwort zurück
→ löscht sie dauerhaft über 6 Tabellen (bei Premium-Editionen)
Der PoC wird am 2026-08-05 veröffentlicht nach dem Embargo der koordinierten Offenlegung.
Siehe Verzeichnis poc/ nach dem Embargo-Datum.
| Szenario | Ergebnis |
|---|---|
| Datenoffenlegung | Namen, E-Mails, Telefonnummern, Termindetails aller Kunden |
| Massenlöschung (Premium) | Alle historischen/zukünftigen Termine dauerhaft über 6 Tabellen gelöscht |
| Keine Wiederherstellungsmöglichkeit | Erfordert vollständige Datenbank-Wiederherstellung aus Backup |
| Datum | Ereignis |
|---|---|
| 2026-07-10 | Schwachstelle entdeckt |
| 2026-07-10 | An WPScan gemeldet |
| 2026-07-22 | CVE-2026-16540 zugewiesen |
| 2026-07-22 | Öffentliche Offenlegung auf WPScan |
| 2026-08-05 | PoC veröffentlicht |