CVE-2025-12037

WP 404 Auto Redirect <= 1.0.5 - Authenticated (Admin+) Stored Cross-Site Scripting

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

Description

The WP 404 Auto Redirect to Similar Post plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 1.0.5 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level permissions and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0.5
PublishedFebruary 17, 2026
Last updatedFebruary 18, 2026

What Changed in the Fix

Changes introduced in v1.0.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-12037 ## 1. Vulnerability Summary The **WP 404 Auto Redirect to Similar Post** plugin (<= 1.0.5) is vulnerable to **Stored Cross-Site Scripting (XSS)** via its administrative settings. The vulnerability exists because the plugin registers a settings group but…

Show full research plan

Exploitation Research Plan - CVE-2025-12037

1. Vulnerability Summary

The WP 404 Auto Redirect to Similar Post plugin (<= 1.0.5) is vulnerable to Stored Cross-Site Scripting (XSS) via its administrative settings. The vulnerability exists because the plugin registers a settings group but fails to adequately sanitize the input in its sanitize_callback and fails to escape the stored values when rendering them on the admin settings page. Specifically, the sanitize_setting function in includes/admin.php only validates the fallback['url'] field, leaving all other settings fields (such as exclusion rules) vulnerable to injection. This allows an authenticated administrator to inject arbitrary scripts that execute when any administrator views the plugin's settings page, especially in environments where unfiltered_html is disabled (like WordPress Multi-site).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/options.php (The standard WordPress Settings API handler).
  • Vulnerable Parameter: wp404arsp_settings[rules][exclude][post_meta] (or other keys within the wp404arsp_settings array).
  • Authentication Level: Administrator (High privilege).
  • Precondition: The site must have unfiltered_html disabled (standard on Multi-site or via DISALLOW_UNFILTERED_HTML in wp-config.php) for this to be considered a vulnerability rather than a feature.
  • Payload: "><script>alert(window.origin)</script>

3. Code Flow

  1. Registration: In includes/admin.php, the function admin_settings() (hooked to admin_init) calls register_setting('wp404arsp_settings', 'wp404arsp_settings', ...) with sanitize_callback set to sanitize_setting.
  2. Weak Sanitization: The sanitize_setting($settings) function in includes/admin.php only performs:
    $settings['fallback']['url'] = sanitize_url($settings['fallback']['url']);
    return $settings;
    
    All other nested keys in the $settings array (like rules, exclude, post_meta) are returned to the database without any filtering.
  3. Retrieval: When an admin visits the settings page, admin_page() calls wp404arsp_settings_get() (defined in class/class-settings.php).
  4. Unescaped Output: The WP_404_Auto_Redirect_Settings::get() function retrieves the option and only escapes the fallback URL using esc_url. Other fields remain raw.
  5. Sink: While the truncation in admin.php obscures the exact HTML for the post_meta field, it follows the pattern of the debug checkbox. The values are echoed into HTML attributes of inputs (likely text inputs for "Exclude Meta") without using esc_attr().

4. Nonce Acquisition Strategy

The vulnerability is in the WordPress Settings API. To exploit it, a valid _wpnonce for the wp404arsp_settings-options action is required.

  1. Navigate: Use browser_navigate to reach the plugin settings page: /wp-admin/options-general.php?page=wp-404-auto-redirect.
  2. Extract: Since the page uses settings_fields('wp404arsp_settings'), a hidden field named _wpnonce is generated within the settings form.
  3. Command:
    browser_eval("document.querySelector('input[name=\"_wpnonce\"]').value")
    
    This retrieves the nonce directly from the DOM in the correct session context.

5. Exploitation Strategy

Step 1: Authentication and Setup

  • Log in to the WordPress instance as an administrator.
  • (Optional but recommended for PoC) Ensure define('DISALLOW_UNFILTERED_HTML', true); is set in wp-config.php.

Step 2: Nonce Retrieval

  • Navigate to the settings page: /wp-admin/options-general.php?page=wp-404-auto-redirect.
  • Use browser_eval to extract the _wpnonce value.

Step 3: Injection Request

  • Send a POST request to /wp-admin/options.php using the http_request tool.
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    option_page=wp404arsp_settings
    &action=update
    &_wpnonce=[EXTRACTED_NONCE]
    &wp404arsp_settings[rules][exclude][post_meta]=%22%3E%3Cscript%3Ealert%28window.origin%29%3C%2Fscript%3E
    &wp404arsp_settings[priority]=999
    &wp404arsp_settings[method]=301
    
    (Note: Include other default settings to ensure the array structure remains valid).

Step 4: Trigger XSS

  • Navigate back to /wp-admin/options-general.php?page=wp-404-auto-redirect.
  • Observe the script execution (the alert will trigger).

6. Test Data Setup

  1. Plugin Installation: Install and activate wp-404-auto-redirect-to-similar-post version 1.0.5.
  2. User: Create or use an existing Administrator account.
  3. Environment: If testing on a standard single-site install, add define( 'DISALLOW_UNFILTERED_HTML', true ); to wp-config.php to simulate the restricted environment where the vulnerability is most relevant.

7. Expected Results

  • The POST request to options.php should return a 302 Found redirect back to the settings page with a settings-updated=true parameter.
  • The wp404arsp_settings option in the wp_options table will now contain the raw HTML payload in the [rules][exclude][post_meta] key.
  • Upon loading the settings page, the browser will execute the injected <script> because the value is echoed inside an input attribute like value="..." without esc_attr(), allowing the payload to break out of the attribute.

8. Verification Steps

  • WP-CLI Verification:
    wp option get wp404arsp_settings --format=json
    
    Verify that the rules -> exclude -> post_meta value contains the raw <script> tag.
  • DOM Verification: Inspect the HTML source of the settings page and look for the injected string:
    <input ... value=""><script>alert(window.origin)</script>" ...>
    

9. Alternative Approaches

  • Payload Variance: If post_meta is not easily accessible in the UI, try injecting into wp404arsp_settings[rules][exclude][term_meta] or wp404arsp_settings[priority]. Even if priority is cast to an integer during its use in template_redirect, it may be rendered as a string in the admin form.
  • Tab Selection: The plugin uses a tabbed interface. The payload might be hidden in the "Post Types" or "Taxonomies" tab. Use browser_eval("jQuery('a[href=\"#settings\"]').click()") or similar to ensure the correct tab is visible if the browser doesn't execute the script immediately.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP 404 Auto Redirect to Similar Post plugin for WordPress is vulnerable to Stored Cross-Site Scripting via its administrative settings in versions up to 1.0.5. This occurs because the plugin fails to sanitize all keys in the settings array upon saving and fails to escape them when rendering the settings page, allowing administrators to inject malicious scripts.

Vulnerable Code

/* File: includes/admin.php (~line 64) */
    function sanitize_setting($settings){
        
        $settings['fallback']['url'] = sanitize_url($settings['fallback']['url']);
        
        return $settings;
        
    }

---

/* File: class/class-settings.php (~line 79) */
        // Esc Fallback
        $settings['fallback']['url'] = esc_url($settings['fallback']['url']);
        
        // Headers
        if(((int)$settings['method'] != 301) && ((int)$settings['method'] != 302)){
            $settings['method'] = 301;
        }
        
        // Return
        return $settings;

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.5/class/class-settings.php /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.6/class/class-settings.php
--- /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.5/class/class-settings.php	2024-02-04 12:33:34.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.6/class/class-settings.php	2025-11-21 04:49:58.000000000 +0000
@@ -79,6 +79,9 @@
         // Esc Fallback
         $settings['fallback']['url'] = esc_url($settings['fallback']['url']);
         
+        // Esc Priority
+        $settings['priority'] = (int) $settings['priority'];
+        
         // Headers
         if(((int)$settings['method'] != 301) && ((int)$settings['method'] != 302)){
             $settings['method'] = 301;
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.5/includes/admin.php /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.6/includes/admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.5/includes/admin.php	2024-02-04 12:33:34.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-404-auto-redirect-to-similar-post/1.0.6/includes/admin.php	2025-11-21 04:49:58.000000000 +0000
@@ -64,6 +64,7 @@
     function sanitize_setting($settings){
         
         $settings['fallback']['url'] = sanitize_url($settings['fallback']['url']);
+        $settings['priority'] = (int) $settings['priority'];
         
         return $settings;

Exploit Outline

The exploit targets the WordPress Settings API by submitting a malicious payload into the plugin's configuration. An authenticated administrator first retrieves a valid CSRF nonce from the plugin's settings page at /wp-admin/options-general.php?page=wp-404-auto-redirect. They then send a POST request to /wp-admin/options.php including the nonce and the payload inside the wp404arsp_settings[rules][exclude][post_meta] or wp404arsp_settings[priority] parameters. The payload, such as a script tag designed to break out of an HTML attribute, is stored in the database. The XSS triggers whenever an administrator subsequently visits the plugin settings page, as the stored value is rendered without proper attribute escaping.

Check if your site is affected.

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