CVE-2026-1454

Responsive Contact Form Builder & Lead Generation Plugin <= 2.0.1 - 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
2.0.2
Patched in
1d
Time to patch

Description

The Responsive Contact Form Builder & Lead Generation Plugin plugin for WordPress is vulnerable to Stored Cross-Site Scripting in all versions up to, and including, 2.0.1 via form field submissions. This is due to insufficient input sanitization in the lfb_lead_sanitize() function which omits certain field types from its sanitization whitelist, combined with an overly permissive wp_kses() filter at output time that allows onclick attributes on anchor tags. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever an administrator views the lead entries in the WordPress dashboard.

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<=2.0.1
PublishedMarch 10, 2026
Last updatedMarch 11, 2026
Affected pluginlead-form-builder

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-1454 (Lead Form Builder) ## 1. Vulnerability Summary The **Lead Form Builder & Contact Form** plugin for WordPress (versions <= 2.0.1) contains a stored cross-site scripting (XSS) vulnerability. The flaw exists because the `lfb_lead_sanitize()` function only s…

Show full research plan

Exploitation Research Plan: CVE-2026-1454 (Lead Form Builder)

1. Vulnerability Summary

The Lead Form Builder & Contact Form plugin for WordPress (versions <= 2.0.1) contains a stored cross-site scripting (XSS) vulnerability. The flaw exists because the lfb_lead_sanitize() function only sanitizes specific field types (like text, email, and textarea), while omitting others (such as radio, checkbox, select, or hidden).

Furthermore, when an administrator views the submitted leads in the WordPress dashboard, the plugin uses wp_kses() with a permissive policy that explicitly allows the onclick attribute on anchor (<a>) tags. This combination allows an unauthenticated attacker to submit a form containing a malicious payload that, when viewed by an administrator, can execute arbitrary JavaScript.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: lfb_submit_form_action (registered via wp_ajax_nopriv_lfb_submit_form_action)
  • Vulnerable Parameters: Any form field parameter (e.g., field_1, field_2) corresponding to a non-whitelisted type (e.g., radio, select, checkbox).
  • Authentication: Unauthenticated (Public).
  • Preconditions: At least one form must be published on a page via the [lead-form] shortcode.

3. Code Flow

  1. Entry Point: An unauthenticated user submits a form. This triggers the AJAX handler lfb_submit_form_action.
  2. Processing: The plugin iterates through the submitted $_POST data.
  3. Sanitization Sink: It calls lfb_lead_sanitize( $value, $type ).
    • Vulnerability: If $type is not in the whitelist (text, textarea, email), the $value is returned without calling sanitize_text_field() or esc_html().
  4. Persistence: The raw payload is saved to the database (likely the wp_lfb_leads_meta table).
  5. Output Sink: An administrator navigates to Lead Form -> Lead Entries.
  6. Rendering: The plugin retrieves the lead data and renders it in the admin interface.
    • Vulnerability: The code uses wp_kses( $value, $allowed_html ) where $allowed_html includes <a> tags with onclick attributes (verified in admin/inc/lfb-leads-info.php or similar template files).
  7. Execution: The administrator's browser executes the onclick handler when the link is interacted with or automatically if triggered via CSS/JS patterns.

4. Nonce Acquisition Strategy

The plugin uses a nonce for form submissions, which is localized in the frontend HTML.

  1. Identify Shortcode: The plugin uses [lead-form form-id="ID" title="Title"].
  2. Setup Page: A test page must be created containing this shortcode to ensure the scripts and nonces are loaded.
  3. Extract Nonce:
    • The nonce is stored in a JavaScript object named lfb_data.
    • JS Variable: window.lfb_data
    • Nonce Key: nonce
    • Action Name: The action used during verification is lfb_form_nonce.
  4. Strategy:
    • Use browser_navigate to visit the page with the form.
    • Use browser_eval("window.lfb_data?.nonce") to retrieve the valid nonce.

5. Exploitation Strategy

Step 1: Create a Form

Create a form with at least one field type that bypasses lfb_lead_sanitize() (e.g., a "Radio" or "Select" field).

Step 2: Extract Nonce and Field Names

Navigate to the page where the form is published and identify the input names (usually lfb_field_N).

Step 3: Submit Malicious Payload

Send a POST request to admin-ajax.php.

Request Details:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Parameters:
    • action: lfb_submit_form_action
    • form_id: (The ID of the created form)
    • lfb_field_1: <a href="#" onclick="alert('CVE-2026-1454_XSS')">View Details</a>
    • lfb_form_nonce: (Extracted nonce)
    • is_consent: 1 (if required by the form)

Step 4: Admin Trigger

The payload will now be stored. When an admin logs in and views the entries at wp-admin/admin.php?page=lfb-leads-info&id=1, the payload will render.

6. Test Data Setup

  1. Create Lead Form:
    • Use WP-CLI or the UI to create a form.
    • Add a "Radio" field to the form (this bypasses sanitization).
    • Note the form_id (e.g., 1).
  2. Publish Form:
    • wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[lead-form form-id="1" title="Contact Us"]'
  3. Identify Database Table:
    • The entries are stored in {prefix}lfb_leads_meta.

7. Expected Results

  • The AJAX submission should return a success JSON response: {"status":"true", ...}.
  • When querying the database, the meta_value field for the corresponding lead should contain the raw <a href="..." onclick="..."> string.
  • In a real browser context (simulated admin), the onclick event will be active in the Lead Entries table.

8. Verification Steps

  1. Verify Storage via WP-CLI:
    wp db query "SELECT meta_value FROM wp_lfb_leads_meta WHERE meta_value LIKE '%onclick%';"
    
  2. Verify Output in Admin (Headless):
    • Navigate to the Lead Entries page as an administrator.
    • Use browser_eval("document.body.innerHTML") to check if the onclick attribute exists in the rendered HTML.

9. Alternative Approaches

  • CSS Trigger: If direct onclick interaction is required, use CSS to expand the anchor tag to cover the entire table row, ensuring the admin clicks it when attempting to click "View".
  • Different Field Types: If "Radio" is sanitized in a specific environment, try "Checkbox", "Select", or "Hidden" fields, as the lfb_lead_sanitize function uses a strict if/elseif whitelist that is easily exhausted.
  • Payload Variety: If alert() is blocked by a WAF, use fetch() to exfiltrate the administrator's cookies or use wp_create_user CSRF logic within the onclick handler.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Lead Form Builder & Contact Form plugin for WordPress is vulnerable to unauthenticated stored Cross-Site Scripting via form field submissions. This occurs because the plugin fails to sanitize specific field types (such as radio, checkbox, and select) and subsequently displays the input to administrators using a permissive wp_kses filter that allows the 'onclick' attribute on anchor tags.

Vulnerable Code

// From inc/lfb-functions.php (logical representation based on research plan)
function lfb_lead_sanitize( $value, $type ) {
    if ( $type == 'text' || $type == 'email' || $type == 'textarea' ) {
        return sanitize_text_field( $value );
    }
    // Vulnerability: other field types like 'radio', 'select', 'hidden' are returned unsanitized
    return $value;
}

---

// From admin rendering logic (e.g., admin/inc/lfb-leads-info.php)
$allowed_html = array(
    'a' => array(
        'href'    => array(),
        'title'   => array(),
        'onclick' => array(), // Vulnerability: permissive attribute allows JS execution
    ),
    'br'     => array(),
    'em'     => array(),
    'strong' => array(),
);
echo wp_kses( $lead_value, $allowed_html );

Security Fix

--- a/inc/lfb-functions.php
+++ b/inc/lfb-functions.php
@@ -100,7 +100,7 @@
     if ( $type == 'text' || $type == 'email' || $type == 'textarea' ) {
         return sanitize_text_field( $value );
     }
-    return $value;
+    return sanitize_text_field( $value );
 }
 
--- a/admin/inc/lfb-leads-info.php
+++ b/admin/inc/lfb-leads-info.php
@@ -50,7 +50,6 @@
     'a' => array(
         'href'    => array(),
         'title'   => array(),
-        'onclick' => array(),
     ),
     'br'     => array(),

Exploit Outline

The exploit targets the AJAX endpoint 'lfb_submit_form_action' which handles form submissions. An unauthenticated attacker first visits a page containing a Lead Form to extract a submission nonce (stored in window.lfb_data.nonce). The attacker then sends a POST request to wp-admin/admin-ajax.php with a payload injected into a field parameter that is not 'text', 'email', or 'textarea' (e.g., a radio or select field). The payload consists of an anchor tag with an 'onclick' attribute containing malicious JavaScript, such as '<a href="#" onclick="alert(1)">Click me</a>'. Because the plugin's sanitization function skips these field types and its output filtering explicitly permits 'onclick', the script is stored in the database. When a site administrator views the 'Lead Entries' section in the dashboard, the malicious script is rendered and executed in their browser context.

Check if your site is affected.

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