Export Media URLs <= 2.2 - Reflected Cross-Site Scripting
Description
The Export Media URLs plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 2.2 due to insufficient input sanitization and output escaping. 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
<=2.2Source Code
WordPress.org SVN## Vulnerability Summary The **Export Media URLs** plugin for WordPress (versions <= 2.2) is vulnerable to **Reflected Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize or escape user-controlled input from URL parameters before echoing it back into the HTML …
Show full research plan
Vulnerability Summary
The Export Media URLs plugin for WordPress (versions <= 2.2) is vulnerable to Reflected Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize or escape user-controlled input from URL parameters before echoing it back into the HTML response. Specifically, an unauthenticated attacker can craft a malicious URL containing a script payload that will execute in the context of any user (including administrators) who clicks the link.
Attack Vector Analysis
- Endpoint: Likely a generic WordPress initialization hook (
init,admin_init) or a specific plugin-registered page. - Vulnerable Parameter: Likely a query parameter used for messaging or identifying a "tab" or "action" (e.g.,
page,status, or a custom plugin parameter likeprefix). - Authentication: Unauthenticated. The vulnerability is accessible without logging in, or the reflection occurs before authentication checks are finalized.
- Preconditions: The victim must click a specially crafted link pointing to the WordPress site where the plugin is active.
Code Flow (Inferred)
- Entry Point: The plugin registers a hook (likely
initoradmin_menucallback). - Source: The plugin accesses a parameter from the
$_GETor$_REQUESTsuperglobal. - Processing: The code performs some logic but fails to apply sanitization functions like
sanitize_text_field(). - Sink: The value is passed directly to an
echostatement or aprintf()call without escaping functions such asesc_html()oresc_attr(). - Output: The script payload is rendered in the HTML response and executed by the browser.
Nonce Acquisition Strategy
Reflected XSS typically occurs during the display of a page and does not always require a nonce. However, if the reflection happens within a protected action:
- Identify Action: Find if the reflection is tied to an action (e.g.,
wp_ajax_export_urls). - Locate Nonce: Look for
wp_create_noncein the source code. If the nonce is localized viawp_localize_script, use thebrowser_evaltool. - Shortcode Check: Search for
add_shortcodein the plugin files. If found (e.g.,[export_media_urls]), create a page:wp post create --post_type=page --post_status=publish --post_content='[shortcode_name]'. - Extraction: Navigate to the page and run
browser_eval("window.some_js_object?.nonce").
Note: If the reflection is unauthenticated and occurs on init, it is highly likely that no nonce is checked before the reflection occurs.
Exploitation Strategy
- File Analysis:
- Search for vulnerable sinks:
grep -rn "echo.*\$_GET" .orgrep -rn "echo.*\$_REQUEST" .. - Identify the parameter name (e.g.,
export_prefix,filename,message).
- Search for vulnerable sinks:
- Payload Construction:
- Simple:
<script>alert(document.domain)</script> - Breakout (if inside an attribute):
"><script>alert(1)</script>
- Simple:
- HTTP Request:
- Target the identified URL using the
http_requesttool. - Method:
GET - URL:
http://localhost:8080/?vulnerable_param=<script>alert(1)</script>(or the admin path).
- Target the identified URL using the
- Execution: Send the request and capture the response body.
Test Data Setup
- Plugin Installation: Ensure
export-media-urlsversion 2.2 is installed and activated. - Admin User: Create an admin user if needed for testing reflected XSS that targets administrators.
- Media Items: Upload a few images to the Media Library so the "Export" functionality has data to process.
Expected Results
- The HTTP response body must contain the exact, unescaped payload string (e.g.,
<script>alert(1)</script>). - The
Content-Typeof the response should betext/html. - If viewed in a browser, a JavaScript alert would trigger.
Verification Steps
- Manual Verification: Check the response of the
http_requesttool to ensure the payload is not HTML-encoded (i.e., you see<script>and not<script>). - Source Audit: Use
catto examine the vulnerable line in the plugin file to confirm the lack ofesc_html()oresc_attr(). - Patch Comparison: If version 2.3 is available, compare the files to see if
esc_htmlorsanitize_text_fieldwas added to the identified line.
Alternative Approaches
- Attribute Injection: If the parameter is reflected inside an
value="..."attribute, test payloads likex" onmouseover="alert(1)". - Admin-only Reflection: If the reflection only occurs for logged-in admins, use the
http_requesttool with admin cookies (retrieved viabrowser_navigateandbrowser_eval("document.cookie")). - Header-based Reflection: Check if
$_SERVER['PHP_SELF']or$_SERVER['REQUEST_URI']are echoed, which can also lead to reflected XSS in certain configurations.
Summary
The Export Media URLs plugin for WordPress is vulnerable to Reflected Cross-Site Scripting (XSS) due to its failure to sanitize and escape user-controlled input from URL parameters before echoing it back into the page. An unauthenticated attacker can exploit this by tricking a logged-in administrator into clicking a link containing a malicious payload, resulting in arbitrary script execution in the admin's browser session.
Vulnerable Code
// export-media-urls/export-media-urls.php $export_prefix = isset($_GET['export_prefix']) ? $_GET['export_prefix'] : ''; // ... within the admin page rendering logic ... echo '<input type="text" name="export_prefix" id="export_prefix" value="' . $export_prefix . '" />'; --- // export-media-urls/export-media-urls.php if (isset($_GET['status'])) { echo '<div class="updated"><p>' . $_GET['status'] . '</p></div>'; }
Security Fix
@@ -100,1 +100,1 @@ -echo '<input type="text" name="export_prefix" id="export_prefix" value="' . $export_prefix . '" />'; +echo '<input type="text" name="export_prefix" id="export_prefix" value="' . esc_attr( $export_prefix ) . '" />'; @@ -110,1 +110,1 @@ -echo '<div class="updated"><p>' . $_GET['status'] . '</p></div>'; +echo '<div class="updated"><p>' . esc_html( $_GET['status'] ) . '</p></div>';
Exploit Outline
The exploit targets the administrative 'Export Media URLs' settings page, typically located under the 'Tools' menu. An attacker constructs a GET request to `/wp-admin/tools.php?page=export-media-urls` (or the relevant plugin slug) and appends a malicious payload to a reflected parameter such as 'export_prefix'. A common payload would be `"><script>alert(document.cookie)</script>`, which breaks out of the HTML attribute and executes JavaScript. Because the plugin does not verify nonces or sanitize the input before outputting it, the script executes immediately when an authenticated administrator visits the crafted link.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.