CVE-2026-25369

Flexmls® IDX Plugin <= 3.15.9 - Reflected Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.1
CVSS Score
6.1
CVSS Score
medium
Severity
3.15.10
Patched in
4d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=3.15.9
PublishedMarch 16, 2026
Last updatedMarch 19, 2026
Affected pluginflexmls-idx

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

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, or search_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

  1. A user sends a GET request to a WordPress page with a malicious payload in a specific URL parameter.
  2. WordPress initializes and loads the Flexmls® IDX Plugin.
  3. The plugin's frontend handler or shortcode callback (e.g., flexmls_idx_shortcode_handler or similar function registered via add_shortcode) is invoked.
  4. The code retrieves the malicious parameter directly from $_GET or $_REQUEST.
  5. 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.
  6. Sink: An echo, printf, or similar construct without an escaping function like esc_attr() or esc_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:

  1. Identify Nonce Key: Search for check_ajax_referer or wp_verify_nonce in the plugin code.
  2. Locate Localization: Find the wp_localize_script call that exposes the nonce.
    • Search command: grep -rn "wp_localize_script" .
  3. 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]'
  4. Extract via Browser: Navigate to the page and use browser_eval to extract the variable:
    • browser_eval("window.flex_idx_params?.nonce") (Replace flex_idx_params and nonce with actual keys found in step 2).

5. Exploitation Strategy

  1. Source Discovery: Run the following command to find potential reflected parameters:
    • grep -rnP "echo\s+\\\$_(GET|REQUEST|POST)" wp-content/plugins/flexmls-idx/
  2. Target Identification: Look for parameters used in frontend display files (e.g., in includes/ or public/). Let's assume the parameter is idx-link.
  3. Craft Payload: Use a standard alert-based XSS canary:
    • "><script>alert(document.domain)</script>
  4. HTTP Request: Use http_request to 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
  5. Execution Verification: Use browser_navigate to the URL and check for the alert dialog.

6. Test Data Setup

  1. Activate Plugin: wp plugin activate flexmls-idx
  2. 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]'
  3. 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., &lt;script&gt;).
  • When navigating to the URL in a browser, the JavaScript alert(document.domain) should execute.

8. Verification Steps

  1. Manual Check: Inspect the page source via http_request and search for the script tag.
  2. 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.
  3. Code Audit: Verify the patch (v3.15.10) by checking if esc_attr() or sanitize_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="..."] where link is populated by $_GET['link']).
Research Findings
Static analysis — not yet PoC-verified

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

--- a/wp-content/plugins/flexmls-idx/includes/class-flexmls-idx-shortcodes.php
+++ b/wp-content/plugins/flexmls-idx/includes/class-flexmls-idx-shortcodes.php
@@ -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.