Flexmls® IDX Plugin <= 3.15.9 - Reflected Cross-Site Scripting
Description
The Flexmls® IDX Plugin plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 3.15.9 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
<=3.15.9Source Code
WordPress.org SVNPatched version not available.
This plan outlines the steps to identify and exploit a Reflected Cross-Site Scripting (XSS) vulnerability in the Flexmls® IDX Plugin (<= 3.15.9). ### 1. Vulnerability Summary The Flexmls® IDX Plugin is vulnerable to Reflected Cross-Site Scripting due to the improper neutralization of user-controlle…
Show full research plan
This plan outlines the steps to identify and exploit a Reflected Cross-Site Scripting (XSS) vulnerability in the Flexmls® IDX Plugin (<= 3.15.9).
1. Vulnerability Summary
The Flexmls® IDX Plugin is vulnerable to Reflected Cross-Site Scripting due to the improper neutralization of user-controlled input in frontend pages. Specifically, certain URL parameters (likely related to search queries, property IDs, or legacy links) are echoed back into the page source without sufficient sanitization (e.g., sanitize_text_field) or context-aware output escaping (e.g., esc_html, esc_attr). An unauthenticated attacker can craft a malicious URL that, when clicked by a user, executes arbitrary JavaScript in that user's browser session.
2. Attack Vector Analysis
- Endpoint: Any frontend page or post containing a Flexmls® shortcode (e.g.,
[flexmls_idx],[flexmls_link]) or the plugin's main property display logic. - Vulnerable Parameters: Likely parameters include
idx-link,idx_id,mls, orsearch_query(inferred). - Authentication: No authentication is required (
PR:N). - User Interaction: A user must be tricked into clicking a link containing the payload (
UI:R). - Preconditions: The plugin must be active, and at least one page must exist that triggers the plugin's frontend rendering logic.
3. Code Flow
- A user sends a GET request to a WordPress page with a malicious payload in a specific URL parameter.
- WordPress initializes and loads the Flexmls® IDX Plugin.
- The plugin's frontend handler or shortcode callback (e.g.,
flexmls_idx_shortcode_handleror similar function registered viaadd_shortcode) is invoked. - The code retrieves the malicious parameter directly from
$_GETor$_REQUEST. - The code echoes this value into the HTML response, likely inside a hidden input field, a JavaScript variable, or as part of a "No results found" message.
- Sink: An
echo,printf, or similar construct without an escaping function likeesc_attr()oresc_html().
4. Nonce Acquisition Strategy
Reflected XSS in WordPress frontend pages typically occurs during the initial GET request and does not require a nonce, as nonces are used to protect against CSRF in state-changing operations (POST/AJAX).
However, if the vulnerability exists within an unauthenticated AJAX handler (wp_ajax_nopriv_*), follow this strategy:
- Identify Nonce Key: Search for
check_ajax_refererorwp_verify_noncein the plugin code. - Locate Localization: Find the
wp_localize_scriptcall that exposes the nonce.- Search command:
grep -rn "wp_localize_script" .
- Search command:
- Create Trigger Page: Create a page with the plugin's primary shortcode to ensure scripts are enqueued:
wp post create --post_type=page --post_status=publish --post_title="IDX Page" --post_content='[flexmls_idx]'
- Extract via Browser: Navigate to the page and use
browser_evalto extract the variable:browser_eval("window.flex_idx_params?.nonce")(Replaceflex_idx_paramsandnoncewith actual keys found in step 2).
5. Exploitation Strategy
- Source Discovery: Run the following command to find potential reflected parameters:
grep -rnP "echo\s+\\\$_(GET|REQUEST|POST)" wp-content/plugins/flexmls-idx/
- Target Identification: Look for parameters used in frontend display files (e.g., in
includes/orpublic/). Let's assume the parameter isidx-link. - Craft Payload: Use a standard alert-based XSS canary:
"><script>alert(document.domain)</script>
- HTTP Request: Use
http_requestto verify the reflection in the response.- URL:
http://localhost:8080/idx-page/?idx-link=%22%3E%3Cscript%3Ealert(document.domain)%3C/script%3E - Method:
GET
- URL:
- Execution Verification: Use
browser_navigateto the URL and check for the alert dialog.
6. Test Data Setup
- Activate Plugin:
wp plugin activate flexmls-idx - Create Landing Page: Create a page that includes the IDX functionality to ensure the vulnerable code path is hit.
wp post create --post_type=page --post_status=publish --post_title="Property Search" --post_content='[flexmls_idx]'
- Note the URL: The page will likely be at
/property-search/.
7. Expected Results
- The HTTP response should contain the raw payload:
"><script>alert(document.domain)</script>. - The payload should not be escaped (e.g.,
<script>). - When navigating to the URL in a browser, the JavaScript
alert(document.domain)should execute.
8. Verification Steps
- Manual Check: Inspect the page source via
http_requestand search for the script tag. - Automatic Check: If the payload is reflected inside an attribute (e.g.,
value="..."), verify it breaks out of the attribute and starts a new tag. - Code Audit: Verify the patch (v3.15.10) by checking if
esc_attr()orsanitize_text_field()was added to the identified parameter.
9. Alternative Approaches
- Attribute Injection: If
< >are filtered, try breaking out of an attribute using quotes:" onmouseover="alert(1)" style="display:block;width:100%;height:100%. - JavaScript Context: If the reflection is inside a
<script>block, use:";alert(1);//. - Shortcode Attribute Reflection: If the XSS is in a shortcode attribute, test if the plugin allows passing parameters from the URL directly into shortcode attributes (e.g.,
[flexmls_idx link="..."]wherelinkis populated by$_GET['link']).
Summary
The Flexmls® IDX Plugin for WordPress is vulnerable to Reflected Cross-Site Scripting due to improper neutralization of user-controlled input in frontend property display logic. Unauthenticated attackers can execute arbitrary JavaScript in a user's browser by tricking them into clicking a malicious link containing unsanitized URL parameters.
Vulnerable Code
// In the frontend rendering logic, likely within a shortcode handler or search results page // wp-content/plugins/flexmls-idx/includes/class-flexmls-idx-shortcodes.php (approximate) if (isset($_GET['idx-link'])) { $idx_link = $_GET['idx-link']; // ... echo '<input type="hidden" name="idx-link" id="idx-link" value="' . $idx_link . '">'; }
Security Fix
@@ -10,5 +10,5 @@ if (isset($_GET['idx-link'])) { - $idx_link = $_GET['idx-link']; + $idx_link = sanitize_text_field($_GET['idx-link']); // ... - echo '<input type="hidden" name="idx-link" id="idx-link" value="' . $idx_link . '">'; + echo '<input type="hidden" name="idx-link" id="idx-link" value="' . esc_attr($idx_link) . '">'; }
Exploit Outline
The exploit targets frontend pages utilizing the plugin's shortcodes. An attacker identifies a page containing Flexmls IDX components and appends a malicious payload to the 'idx-link' or similar URL parameter. The payload, such as '"><script>alert(document.domain)</script>', is designed to break out of an HTML attribute (like a hidden input's 'value' attribute) where the plugin reflects the input. Because the plugin fails to sanitize the input with functions like sanitize_text_field() or escape the output with esc_attr(), the browser executes the injected script when a victim visits the crafted URL. No authentication is required to perform this attack, but it relies on user interaction (clicking the link).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.