[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f_fNGgjc1UGuFQGURf9kjetyA1SUJuNSvT1boeRpH6kE":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-52702","seo-redirection-plugin-301-redirect-manager-unauthenticated-stored-cross-site-scripting","SEO Redirection Plugin – 301 Redirect Manager \u003C= 9.17 - Unauthenticated Stored Cross-Site Scripting","The SEO Redirection Plugin – 301 Redirect Manager plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 9.17 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.","seo-redirection",null,"\u003C=9.17","9.18","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-06-12 00:00:00","2026-06-15 19:18:55",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F85fdd63e-a683-4bed-ac1a-3d8b8cbd67d2?source=api-prod",4,[22,23,24,25,26],"common\u002Fcontrols\u002Fdatagrid.class.php","common\u002Fstyle.css","common\u002Futil.php","readme.txt","seo-redirection.php","researched",false,3,"This exploitation research plan targets **CVE-2026-52702**, an unauthenticated stored cross-site scripting (XSS) vulnerability in the **SEO Redirection Plugin – 301 Redirect Manager** (versions \u003C= 9.17).\n\n### 1. Vulnerability Summary\nThe vulnerability arises from the plugin's feature that logs 404 errors and redirection hits. When a visitor triggers a 404 error or a configured redirect, the plugin records metadata about the request—including the **Request URL**, **Referer**, and **User-Agent**—into the WordPress database. \n\nBecause the plugin fails to properly sanitize this input before storage or, more critically, fails to escape it when displaying the history logs in the admin dashboard (using the `datagrid` class), an unauthenticated attacker can inject malicious scripts into the logs. These scripts execute when an administrator views the \"404 Errors\" or \"History\" tabs.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** Any non-existent URL (to trigger a 404 log) or a URL that matches an existing redirection rule.\n*   **Vulnerable Parameters:** `HTTP_REFERER` header, `HTTP_USER_AGENT` header, or the `REQUEST_URI` (specifically query parameters).\n*   **Authentication:** None (Unauthenticated).\n*   **Preconditions:** The plugin must have 404 logging enabled (this is a core feature and typically enabled by default).\n\n### 3. Code Flow\n1.  **Entry Point:** A visitor requests a URL that triggers `WPSR_redirect` (hooked to `wp` in `seo-redirection.php`).\n2.  **Detection:** If the request results in a 404, the plugin calls a logging function (e.g., `WPSR_add_404_log`).\n3.  **Data Collection:** The logging function retrieves request data. In `common\u002Futil.php`, the `get_current_URL()` and `get_ref()` functions are used to fetch the URL and Referer.\n    *   *Bypass Note:* `util.php` shows `urldecode(sanitize_text_field($_SERVER['QUERY_STRING']))` in `WPSR_get_current_parameters`. Applying `urldecode` *after* sanitization effectively re-introduces malicious characters like `\u003C` and `>`.\n4.  **Storage:** The unsanitized\u002Fdecoded string is inserted into the 404 history table (e.g., `wp_WP_SEO_404_History`).\n5.  **Sink (Admin View):** An administrator navigates to the plugin settings: `wp-admin\u002Foptions-general.php?page=seo-redirection.php&tab=404`.\n6.  **Rendering:** The page uses the `datagrid` class (`common\u002Fcontrols\u002Fdatagrid.class.php`). The grid calls `add_data_col` or `add_html_col` to display the log entries. If these columns are rendered without `esc_html()`, the stored script executes.\n\n### 4. Nonce Acquisition Strategy\n**No nonce is required** for the injection phase because the logging mechanism is triggered by unauthenticated frontend requests. \n\nTo verify the exploit as an admin:\n1.  The agent must log in as an administrator.\n2.  Navigate to the 404 log tab: `admin_url('options-general.php?page=seo-redirection.php&tab=404')`.\n3.  No nonce is needed to *view* the logs, though one may be needed if the exploit requires interacting with the \"Delete\" or \"Redirect\" buttons in the grid.\n\n### 5. Exploitation Strategy\nThe goal is to trigger a 404 error while providing a malicious payload in the Referer or URL.\n\n**Step 1: Trigger 404 via Malicious Referer**\n*   **Method:** GET\n*   **URL:** `http:\u002F\u002F[target]\u002Fthis-page-does-not-exist-123`\n*   **Headers:**\n    *   `Referer: \u003Cscript>alert('XSS_REFERER')\u003C\u002Fscript>`\n    *   `User-Agent: \u003Cimg src=x onerror=alert('XSS_UA')>`\n\n**Step 2: Trigger 404 via Malicious Query String**\n*   **Method:** GET\n*   **URL:** `http:\u002F\u002F[target]\u002Ftrigger-404?debug=%3Cscript%3Ealert('XSS_URL')%3C\u002Fscript%3E`\n*   **Note:** Use URL encoding to ensure the payload survives the initial HTTP request.\n\n**Step 3: Admin Trigger**\n*   Use `browser_navigate` to visit the 404 History tab.\n*   Monitor for dialogs\u002Falerts using `browser_eval`.\n\n### 6. Test Data Setup\n1.  Ensure the plugin **SEO Redirection** (v9.17) is active.\n2.  Ensure 404 logging is enabled in the plugin settings (usually default).\n3.  Create a \"Canary\" 404 request to confirm logging is working:\n    *   `GET \u002Fcanary-404`\n    *   Verify entry appears in `wp-admin\u002Foptions-general.php?page=seo-redirection.php&tab=404`.\n\n### 7. Expected Results\n*   The malicious payload is stored in the database table tracking 404 errors.\n*   When an administrator views the 404 History tab, the browser executes the injected JavaScript.\n*   The `datagrid` should render the payload as raw HTML instead of literal text.\n\n### 8. Verification Steps\nAfter sending the malicious HTTP requests, verify the storage in the database via WP-CLI:\n```bash\n# Check if the payload exists in the 404 history table\nwp db query \"SELECT * FROM $(wp db prefix)WP_SEO_404_History ORDER BY id DESC LIMIT 5;\"\n```\nVerify the output rendering:\n1.  Navigate to the admin page.\n2.  Inspect the HTML source of the table: `browser_eval(\"document.querySelector('.grid').innerHTML\")`.\n3.  Look for the unescaped `\u003Cscript>` or `\u003Cimg>` tags.\n\n### 9. Alternative Approaches\n*   **Redirection Hit Vector:** If the site has an existing redirect (e.g., `\u002Fold` -> `\u002Fnew`), request the \"from\" URL with a malicious Referer. The plugin might log successful redirects in a \"History\" tab (`tab=history`).\n*   **Admin Bar Vector:** The plugin displays the latest 404 in the Admin Bar for logged-in users (see `WPSR_add_link_to_admin_bar`). If the `relative_url` is reflected there without escaping, XSS will trigger on every admin page load, not just the settings page.\n    *   *Code Reference:* `seo-redirection.php` lines 135-155 uses `$relative_url` in `admin_url(...)` and node titles. Check if `add_node` titles are escaped.","The SEO Redirection Plugin for WordPress is vulnerable to unauthenticated stored Cross-Site Scripting (XSS) due to insufficient sanitization and escaping of request metadata, such as the Referer header, User-Agent, and visitor IP address. Attackers can inject malicious scripts by triggering 404 errors or redirection events, which are then executed in the context of an administrator viewing the plugin's log dashboard.","\u002F* common\u002Futil.php line 352 *\u002F\npublic function get_visitor_IP()\n{\n\t$ipaddress = sanitize_text_field($_SERVER['REMOTE_ADDR']);\n\t\n\tif (!empty($_SERVER['HTTP_CLIENT_IP'])) {\n\t\t$ipaddress = sanitize_text_field($_SERVER['HTTP_CLIENT_IP']);\n\t} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {\n\t\t$ipaddress = sanitize_text_field($_SERVER['HTTP_X_FORWARDED_FOR']);\n\t}\n\t\n\treturn sanitize_text_field($ipaddress) ;\n}\n\n---\n\n\u002F* common\u002Futil.php line 445 *\u002F\npublic function WPSR_get_current_parameters($remove_parameter=\"\")\n{\t\n\t\n\tif($_SERVER['QUERY_STRING']!='')\n\t{\n\t\t$qry = '?' . urldecode(sanitize_text_field($_SERVER['QUERY_STRING']));\n\n---\n\n\u002F* common\u002Fcontrols\u002Fdatagrid.class.php around line 442 (inferred from patch) *\u002F\nif (is_array($ar)) {\n    foreach ($ar as $key => $value) {\n        $key_var = \"db_\" . $key;\n        $html = str_ireplace('{' . $key_var . '}', ${$key_var} ?? '', $html);\n    }\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.17\u002Fcommon\u002Fcontrols\u002Fdatagrid.class.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.18\u002Fcommon\u002Fcontrols\u002Fdatagrid.class.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.17\u002Fcommon\u002Fcontrols\u002Fdatagrid.class.php\t2026-04-14 14:33:52.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.18\u002Fcommon\u002Fcontrols\u002Fdatagrid.class.php\t2026-06-06 11:23:48.000000000 +0000\n@@ -442,7 +442,10 @@\n \t\t\t\t\tif (is_array($ar)) {\n \t\t\t\t\t\tforeach ($ar as $key => $value) {\n \t\t\t\t\t\t\t$key_var = \"db_\" . $key;\n-\t\t\t\t\t\t\t$html = str_ireplace('{' . $key_var . '}', ${$key_var} ?? '', $html);\n+\t\t\t\t\t\t\t\u002F\u002F Security: escape DB values before injecting them into HTML.\n+\t\t\t\t\t\t\t\u002F\u002F Values like {db_ip} are placed inside both HTML attributes\n+\t\t\t\t\t\t\t\u002F\u002F and text content; esc_attr() is safe for both.\n+\t\t\t\t\t\t\t$html = str_ireplace('{' . $key_var . '}', esc_attr(${$key_var} ?? ''), $html);\n \t\t\t\t\t\t}\n \t\t\t\t\t}\n \t\t\t\t\t$row[$i] = $html;\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.17\u002Fcommon\u002Futil.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.18\u002Fcommon\u002Futil.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.17\u002Fcommon\u002Futil.php\t2026-04-14 14:33:52.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fseo-redirection\u002F9.18\u002Fcommon\u002Futil.php\t2026-06-06 11:23:48.000000000 +0000\n@@ -352,15 +352,25 @@\n \n public function get_visitor_IP()\n {\n-\t$ipaddress = sanitize_text_field($_SERVER['REMOTE_ADDR']);\n+\t$ipaddress = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field($_SERVER['REMOTE_ADDR']) : '';\n \t\n \tif (!empty($_SERVER['HTTP_CLIENT_IP'])) {\n \t\t$ipaddress = sanitize_text_field($_SERVER['HTTP_CLIENT_IP']);\n \t} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {\n-\t\t$ipaddress = sanitize_text_field($_SERVER['HTTP_X_FORWARDED_FOR']);\n+\t\t\u002F\u002F X-Forwarded-For may contain a comma-separated list; take the first entry.\n+\t\t$forwarded = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);\n+\t\t$ipaddress = sanitize_text_field(trim($forwarded[0]));\n \t}\n \t\n-\treturn sanitize_text_field($ipaddress) ;\n+\t\u002F\u002F Security: validate that the value is actually an IP address.\n+\t\u002F\u002F sanitize_text_field() does not strip HTML attribute breakers like\n+\t\u002F\u002F double quotes or event-handler payloads, which previously allowed\n+\t\u002F\u002F stored XSS when the IP was rendered in the admin dashboard.\n+\tif (!filter_var($ipaddress, FILTER_VALIDATE_IP)) {\n+\t\t$ipaddress = '';\n+\t}\n+\t\n+\treturn $ipaddress;\n }","1. Identify an endpoint on the WordPress site that triggers a 404 error (any non-existent URL).\n2. Craft an HTTP request to this endpoint containing an XSS payload (e.g., `\u003Cscript>alert(document.cookie)\u003C\u002Fscript>`) in headers like `Referer` or `User-Agent`.\n3. Alternatively, supply a malicious payload in the query string of the URL; the plugin's `WPSR_get_current_parameters` function decodes the query string after sanitization, potentially re-introducing malicious characters.\n4. If the server trusts proxy headers, the `X-Forwarded-For` header can also be used to inject a payload.\n5. Wait for an administrator to log into the WordPress dashboard and navigate to 'Settings' > 'SEO Redirection' > '404 Errors' or 'History'.\n6. The payload executes when the `datagrid` class renders the log table, as it replaces placeholders with raw database values without output escaping.","gemini-3-flash-preview","2026-06-26 00:45:27","2026-06-26 00:47:09",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","9.17","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fseo-redirection\u002Ftags\u002F9.17","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fseo-redirection.9.17.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fseo-redirection\u002Ftags\u002F9.18","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fseo-redirection.9.18.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fseo-redirection\u002Ftags"]