[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fQzQMsfzy7Uf6lDmuTIh2RlNNYOFqtL8UiwXpgNtM37E":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":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"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":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2025-9989","broadstreet-authenticated-admin-stored-cross-site-scripting","Broadstreet \u003C= 1.53.1 - Authenticated (Admin+) Stored Cross-Site Scripting","The Broadstreet plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 1.53.1 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.","broadstreet",null,"\u003C=1.53.1","1.53.2","medium",4.4,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:H\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-05-12 15:28:56","2026-05-13 04:26:45",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ff9b6e9a7-1ac5-45d0-83c3-a3f79935904a?source=api-prod",1,[22,23,24],"Broadstreet\u002FConfig.php","broadstreet.php","readme.txt","researched",false,3,"This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in the **Broadstreet** plugin (\u003C= 1.53.1). The vulnerability allows high-privileged users (Administrators) to inject malicious scripts into admin settings, which is particularly critical in multi-site environments or hardened installations where `unfiltered_html` is disabled.\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Authenticated (Admin+) Stored XSS\n*   **Location:** Admin settings page (typically `Settings -> Broadstreet`)\n*   **Cause:** The plugin fails to sanitize user-provided configuration values before storing them and fails to escape those values when rendering them back in the administration interface.\n*   **Affected Versions:** \u003C= 1.53.1\n*   **Patch:** Version 1.53.2 introduces sanitization (e.g., `sanitize_text_field`) and escaping (e.g., `esc_attr`).\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Foptions-general.php?page=broadstreet-settings` (inferred slug) or a custom POST handler in `Broadstreet_Core`.\n*   **Vulnerable Parameter:** Likely parameters related to the \"Access Token\" or other configuration settings handled by `Broadstreet_Config`.\n*   **Authentication:** Requires Administrator privileges.\n*   **Precondition:** `unfiltered_html` must be disabled (e.g., in a Multi-site environment or by defining `DISALLOW_UNFILTERED_HTML` in `wp-config.php`). This prevents the default behavior where Admins can post raw HTML.\n\n### 3. Code Flow\n1.  **Entry Point:** The plugin registers an admin menu via `Broadstreet_Core` (referenced in `broadstreet.php`).\n2.  **Configuration Storage:** When an admin saves settings, the plugin likely captures `$_POST` data and uses `Broadstreet_Config::set($key, $value)` or `update_option()`. \n    - *Source Path:* `Broadstreet\u002FConfig.php` contains the `setValue($key, $value)` method which stores configuration in the `$_config` array.\n3.  **Persistence:** The configuration is persisted to the database (likely as a single option or individual options).\n4.  **Sink:** When the settings page is reloaded, the plugin retrieves values using `Broadstreet_Config::get($key)`. The values are echoed into the HTML (e.g., inside an `\u003Cinput>` tag's `value` attribute or as text) without using `esc_attr()` or `esc_html()`.\n\n### 4. Nonce Acquisition Strategy\nThe Broadstreet plugin settings page uses WordPress standard security practices for admin forms.\n\n1.  **Identify Page:** The settings page is located at `\u002Fwp-admin\u002Foptions-general.php?page=broadstreet-settings`.\n2.  **Navigation:** Use `browser_navigate` to access the settings page as an Administrator.\n3.  **Extraction:** The form will contain a hidden field for the nonce. \n    - **JS Variable (Inferred):** Broadstreet may localize data. Check for `window.broadstreet_data?.nonce`.\n    - **DOM Extraction:** Use `browser_eval` to extract the `_wpnonce` field from the settings form.\n    - **Action String:** The nonce action is likely `broadstreet-options` or `update`.\n\n**Extraction Command:**\n```javascript\nbrowser_eval(\"document.querySelector('input[name=\\\"_wpnonce\\\"]')?.value || document.querySelector('#_wpnonce')?.value\")\n```\n\n### 5. Exploitation Strategy\nThe goal is to inject a payload into an admin setting field that executes when the admin page is viewed.\n\n1.  **Preparation:**\n    - Log in as Administrator.\n    - Ensure `DISALLOW_UNFILTERED_HTML` is true to simulate the vulnerable environment.\n2.  **Identify Form Fields:** Inspect the HTML at the settings page to find the specific parameter names (e.g., `broadstreet_access_token` or `broadstreet_options[access_token]`).\n3.  **Craft Payload:** \n    - Standard attribute breakout: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n    - If inside an attribute: `x\" onmouseover=\"alert(1)\"`\n4.  **Send Exploit Request:** Use `http_request` to send a POST request mimicking the settings save action.\n\n**Example Request (Template):**\n- **Method:** `POST`\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Foptions.php` (if using Settings API) or the plugin's own slug.\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:**\n  ```text\n  option_page=broadstreet_options&\n  action=update&\n  _wpnonce=[EXTRACTED_NONCE]&\n  broadstreet_access_token=\">\u003Cscript>alert('XSS')\u003C\u002Fscript>\n  ```\n\n### 6. Test Data Setup\n1.  **Installation:** `wp plugin install broadstreet --version=1.53.1 --activate`\n2.  **Hardening:** Add `define( 'DISALLOW_UNFILTERED_HTML', true );` to `wp-config.php` to ensure the XSS is not \"by design.\"\n3.  **User Creation:** Create a standard admin user if not present.\n\n### 7. Expected Results\n*   Upon submitting the POST request, the server should return a `302 Redirect` back to the settings page.\n*   When the admin page is subsequently loaded, the HTML source of the configuration input will look like:\n    `\u003Cinput ... value=\"\">\u003Cscript>alert('XSS')\u003C\u002Fscript>\">`\n*   The browser will execute the script, triggering an alert box.\n\n### 8. Verification Steps\n1.  **Database Check:** Use WP-CLI to verify the payload is stored raw in the options table.\n    ```bash\n    wp option get broadstreet_options\n    # OR if stored individually\n    wp option get broadstreet_access_token\n    ```\n2.  **Response Inspection:** Verify the unescaped output in the response body via `http_request` (GET).\n    ```bash\n    # Look for the raw payload in the HTML response\n    grep -F \"\u003Cscript>alert('XSS')\u003C\u002Fscript>\"\n    ```\n\n### 9. Alternative Approaches\n*   **Settings API Bypass:** If the plugin does not use `options.php`, check for an `admin_init` hook that handles settings directly. Search for `if (isset($_POST['...']))` in the plugin source (specifically in `Broadstreet\u002FCore.php` if available).\n*   **Different Fields:** If the \"Access Token\" field is sanitized, try other fields like \"Zone IDs\" or \"Keyword Settings\" if the plugin provides them on the settings page.\n*   **AJAX Handler:** Check for any `wp_ajax_` actions that might be used to save individual settings, which could be vulnerable if they call `Broadstreet_Config::set()` without sanitization.","The Broadstreet plugin for WordPress (\u003C= 1.53.1) is vulnerable to Stored Cross-Site Scripting (XSS) because it fails to sanitize and escape administrative settings data. Authenticated attackers with Administrator permissions can inject malicious scripts into configuration fields like the Access Token, which will execute when any administrator views the plugin's settings page, specifically in environments where 'unfiltered_html' is restricted.","\u002F\u002F Broadstreet\u002FConfig.php line 107\n    public function setValue($key, $value)\n    {\n        return $this->_config[$key] = $value;\n    }\n\n---\n\n\u002F\u002F Broadstreet\u002FConfig.php line 119\n    public function getValue($key = FALSE, $default = FALSE)\n    {\n        if($key === FALSE)\n            return $this->_config;\n\n        $config = $this->_config;\n        $keys   = explode('.', $key);\n\n        foreach($keys as $key)\n        {\n            if(array_key_exists($key, $config))\n                $config = $config[$key];\n            else\n                return $default;\n        }\n\n        return $config;\n    }","--- Broadstreet\u002FConfig.php\n+++ Broadstreet\u002FConfig.php\n@@ -109,7 +109,7 @@\n      *\u002F\n     public function setValue($key, $value)\n     {\n-        return $this->_config[$key] = $value;\n+        return $this->_config[$key] = sanitize_text_field($value);\n     }\n \n     \u002F**\n@@ -137,6 +137,6 @@\n                 return $default;\n         }\n \n-        return $config;\n+        return is_string($config) ? esc_attr($config) : $config;\n     }","1. Log into the WordPress admin panel with Administrator privileges on a site with 'unfiltered_html' disabled (e.g., a Multisite environment).\n2. Navigate to the Broadstreet settings page (typically Settings -> Broadstreet).\n3. Identify a configuration input field such as the 'Access Token' and extract the required security nonce (`_wpnonce`) from the page source.\n4. Craft a POST request to update the settings, injecting an XSS payload into the target field: `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\n5. Upon submission, the plugin saves the raw script to the database. The script will execute whenever the settings page is rendered in an administrator's browser, as the value is echoed into the HTML source without proper output escaping.","gemini-3-flash-preview","2026-05-14 18:03:17","2026-05-14 18:04:08",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","1.53.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbroadstreet\u002Ftags\u002F1.53.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbroadstreet.1.53.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbroadstreet\u002Ftags\u002F1.53.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbroadstreet.1.53.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbroadstreet\u002Ftags"]