Optimole <= 4.2.3 - Reflected Cross-Site Scripting via Page Profiler URL
Description
The Optimole – Optimize Images in Real Time plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via URL paths in versions up to, and including, 4.2.3 This is due to insufficient output escaping on user-supplied URL paths in the get_current_url() function, which are inserted into JavaScript code via str_replace() without proper JavaScript context escaping in the replace_content() function. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v4.2.4
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-5226 - Optimole Reflected XSS ## 1. Vulnerability Summary The **Optimole** plugin for WordPress (versions <= 4.2.3) contains a reflected cross-site scripting (XSS) vulnerability. The vulnerability resides in the **Page Profiler** feature. Specifically, the plu…
Show full research plan
Exploitation Research Plan: CVE-2026-5226 - Optimole Reflected XSS
1. Vulnerability Summary
The Optimole plugin for WordPress (versions <= 4.2.3) contains a reflected cross-site scripting (XSS) vulnerability. The vulnerability resides in the Page Profiler feature. Specifically, the plugin's get_current_url() function (likely within the OptimoleWP\PageProfiler\Profile class) retrieves the current request's URL path without sufficient sanitization. This unsanitized URL is then injected into a JavaScript block using a simple str_replace() call within the replace_content() function, rather than using proper JavaScript context escaping (like esc_js() or wp_json_encode()).
2. Attack Vector Analysis
- Endpoint: Any frontend WordPress page.
- Trigger: Appending the Page Profiler trigger parameter (likely
?optml_profile=1) to the URL. - Vulnerable Parameter: The URL path itself (Reflected via
$_SERVER['REQUEST_URI']). - Authentication: None (Unauthenticated). The vulnerability is reachable by any visitor who can trigger the Page Profiler output.
- Preconditions: The plugin must be active. The Page Profiler feature must be reachable (usually via query parameter).
3. Code Flow
- Initialization:
Optml_Manager::instance()(ininc/manager.php) instantiates theOptimoleWP\PageProfiler\Profileclass:self::$instance->page_profiler = new Profile(); - Hook Registration: The
Profileclass (likely ininc/page-profiler/profile.php, though file not provided) registers hooks to output the Page Profiler script (e.g.,wp_footerorwp_enqueue_scripts). - URL Retrieval: When the profiler is triggered (e.g., via
?optml_profile=1), the plugin callsget_current_url()to identify the page being profiled. This function typically returns$_SERVER['REQUEST_URI']. - Insecure Injection: The
replace_content()function contains a template JavaScript string with a placeholder. It usesstr_replace()to swap the placeholder with the result ofget_current_url():// Inferred logic in replace_content() $js_template = '<script>var optml_data = {"url":"{{URL_PLACEHOLDER}}"};</script>'; $current_url = $this->get_current_url(); // Unescaped /path/";alert(1);// echo str_replace('{{URL_PLACEHOLDER}}', $current_url, $js_template); - Execution: The browser renders the page, encounters the broken JavaScript string, and executes the injected script.
4. Nonce Acquisition Strategy
This is a Reflected XSS vulnerability via a GET request. Based on the vulnerability description and type:
- No Nonce Required: The vulnerability triggers during the rendering of the page itself. Nonces are typically required for state-changing actions (POST/AJAX), but here the "action" is simply visiting a crafted URL.
5. Exploitation Strategy
We will use the http_request tool to perform a GET request to the WordPress site with a malicious URL path designed to break out of a JavaScript string.
Step-by-Step Plan:
Construct Malicious URL:
The payload needs to break out of a JSON-like object or variable assignment.- Context:
{"url":"/index.php/[PAYLOAD]"} - Payload:
";alert(document.domain);var+dummy=" - Full Path:
/index.php/";alert(document.domain);var+dummy="/?optml_profile=1
- Context:
Send Request:
Usehttp_requestto visit the URL. We must ensure the path is sent exactly as intended.// Target URL construction const targetUrl = "http://localhost:8080/index.php/\";alert(document.domain);var+dummy=\"/?optml_profile=1";Analyze Response:
Inspect the HTML source for the Page Profiler script block. Search for the stringoptmland verify if thealertpayload exists unescaped within a<script>tag.
6. Test Data Setup
- Install Plugin: Ensure Optimole version 4.2.3 is installed and active.
- Permalinks: While not strictly required, having "Plain" permalinks (
/index.php/path) or "Post name" permalinks helps in manipulating the path. - Profiler Activation: No specific backend settings are required if the
optml_profile=1parameter is sufficient to trigger the code path.
7. Expected Results
A successful exploit will return an HTML response containing a script block similar to:
<script type="text/javascript">
// ... other code ...
var some_optimole_var = {"url":"/index.php/";alert(document.domain);var dummy="/?optml_profile=1"};
// ...
</script>
The browser (if it were a real user) would execute alert(document.domain).
8. Verification Steps
- Search for Sink: In the response body from
http_request, look for the<script>tag containing the Page Profiler data. - Check Escaping: Confirm that the double quotes (
") and semicolons (;) from the URL path are present verbatim in the response, proving that no JavaScript-context escaping was applied. - Regex Match:
grep -P "var.*optml.*\";alert\(document\.domain\)"
9. Alternative Approaches
If ?optml_profile=1 does not trigger the output:
- Check Authenticated State: Try triggering the profiler while logged in as an administrator (using
browser_navigateand the agent's session). If it only triggers for admins, it is still a "Medium" severity Reflected XSS (Admin XSS). - Vary URL Position: If the path injection is blocked by the web server (404/403), try injecting the payload into a query parameter if
get_current_url()captures the full URL including query strings:- URL:
http://localhost:8080/?optml_profile=1&dummy=";alert(1)//
- URL:
- Check for different localization keys: Look for other JS variables like
optimole_profiler_dataoroptmlProfilerin the source ofinc/manager.phporinc/page-profiler/profile.phpif accessible.
Summary
The Optimole plugin for WordPress is vulnerable to Reflected Cross-Site Scripting (XSS) via the Page Profiler feature in versions up to 4.2.3. Unauthenticated attackers can inject arbitrary scripts into the page by crafting a malicious URL path that breaks out of a JavaScript variable assignment within the plugin's profiler script block.
Vulnerable Code
// inc/manager.php (lines 456-462 in version 4.2.3) $hmac = wp_hash( $profile_id . $time . $this->get_current_url(), 'nonce' ); $js_optimizer = str_replace( [ Profile::PLACEHOLDER, Profile::PLACEHOLDER_MISSING, Profile::PLACEHOLDER_TIME, Profile::PLACEHOLDER_HMAC, Profile::PLACEHOLDER_URL ], [ $profile_id, implode( ',', $missing ), strval( $time ), $hmac, $this->get_current_url() ], $js_optimizer );
Security Fix
@@ -453,10 +453,11 @@ if ( ! $this->page_profiler->exists_all( $profile_id ) ) { $missing = $this->page_profiler->missing_devices( $profile_id ); $time = time(); - $hmac = wp_hash( $profile_id . $time . $this->get_current_url(), 'nonce' ); + $url = esc_url( esc_js( $this->get_current_url() ) ); + $hmac = wp_hash( $profile_id . $time . $url, 'nonce' ); $js_optimizer = str_replace( [ Profile::PLACEHOLDER, Profile::PLACEHOLDER_MISSING, Profile::PLACEHOLDER_TIME, Profile::PLACEHOLDER_HMAC, Profile::PLACEHOLDER_URL ], - [ $profile_id, implode( ',', $missing ), strval( $time ), $hmac, $this->get_current_url() ], + [ $profile_id, implode( ',', $missing ), strval( $time ), $hmac, $url ], $js_optimizer ); $html = str_replace( Optml_Admin::get_optimizer_script( true ), $js_optimizer, $html );
Exploit Outline
The exploit targets the Page Profiler feature of the Optimole plugin. 1. Target Endpoint: Any public-facing page on the WordPress site. 2. Methodology: An attacker crafts a URL where the path contains a JavaScript breakout payload. Since the plugin uses the current URL (retrieved via `$_SERVER['REQUEST_URI']`) and reflects it inside a `<script>` tag using `str_replace` without proper escaping, the payload can terminate the existing string and execute arbitrary code. 3. Payload Shape: `/index.php/";alert(document.domain);var+dummy="/?optml_profile=1` 4. Authentication: No authentication is required (Unauthenticated Reflected XSS). The attacker simply needs to trick a logged-in user or an administrator into clicking the crafted link, or target any visitor to execute the script in their browser session.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.