[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fOzP7PIw5AFiVG-EmXGmRHkB2fNw3bIj1mYBDaOrNHkk":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-9187","abandoned-contact-form-7-missing-authorization-to-unauthenticated-arbitrary-post-deletion-via-recoverid-parameter","Abandoned Contact Form 7 \u003C= 2.2 - Missing Authorization to Unauthenticated Arbitrary Post Deletion via 'recover_id' Parameter","The Abandoned Contact Form 7 plugin for WordPress is vulnerable to unauthorized arbitrary post deletion in versions up to, and including, 2.2. This is due to a missing capability check and missing nonce validation in the action__remove_abandoned() function, which is registered to both the wp_ajax_remove_abandoned and wp_ajax_nopriv_remove_abandoned hooks. The handler takes a user-supplied recover_id parameter from $_POST and passes it directly to wp_delete_post() with the force-delete flag set to true, without verifying that the ID belongs to the plugin's own cf7af_data post type. This makes it possible for unauthenticated attackers to permanently delete arbitrary posts, pages, or other content on the affected site by sending a single admin-ajax.","abandoned-contact-form-7",null,"\u003C=2.2","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-06-15 16:26:44","2026-06-16 04:30:21",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa38ebdeb-6ab8-4f1d-9c13-39211a9e97b6?source=api-prod",[],"researched",false,3,"# Exploitation Research Plan: CVE-2026-9187\n\n## 1. Vulnerability Summary\nThe **Abandoned Contact Form 7** plugin (versions \u003C= 2.2) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, the function `action__remove_abandoned()` is registered to both authenticated (`wp_ajax_`) and unauthenticated (`wp_ajax_nopriv_`) AJAX hooks. This function fails to perform capability checks, nonce validation, or verify that the target post belongs to the plugin's intended custom post type (`cf7af_data`). As a result, any unauthenticated user can trigger the permanent deletion of arbitrary WordPress posts, pages, or media.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action:** `remove_abandoned` (inferred from hook registration `wp_ajax_nopriv_remove_abandoned`)\n- **Vulnerable Parameter:** `recover_id` (sent via `$_POST`)\n- **Required Authentication:** None (Unauthenticated)\n- **Preconditions:** The plugin \"Abandoned Contact Form 7\" must be active.\n\n## 3. Code Flow\n1. **Entry Point:** An unauthenticated POST request is sent to `admin-ajax.php` with the parameter `action=remove_abandoned`.\n2. **Hook Execution:** WordPress executes the hook `wp_ajax_nopriv_remove_abandoned`, which calls the handler `action__remove_abandoned()`.\n3. **Missing Checks:** The handler does not call `current_user_can()` or `check_ajax_referer()`.\n4. **Input Processing:** The handler retrieves `$_POST['recover_id']`.\n5. **The Sink:** The handler calls `wp_delete_post( $_POST['recover_id'], true )`. \n    - The first argument is the ID to delete.\n    - The second argument `true` bypasses the Trash and performs a **permanent deletion**.\n6. **Result:** The post associated with the provided ID is deleted from the database regardless of its post type or author.\n\n## 4. Nonce Acquisition Strategy\nAccording to the vulnerability description, this specific vulnerability is exploitable because **nonce validation is entirely missing** in the `action__remove_abandoned()` function. \n\nNo nonce acquisition is required for this exploit.\n\n## 5. Exploitation Strategy\nThe goal is to permanently delete a critical post or page (e.g., the site's front page or a post created by an admin).\n\n### Step-by-Step Plan:\n1. **Target Identification:** Identify the ID of a post or page to delete.\n2. **Payload Construction:** Prepare a POST request to the AJAX endpoint.\n3. **Execution:** Send the request using the `http_request` tool.\n\n### Technical Request Details:\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method:** `POST`\n- **Headers:** \n    - `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:** \n    - `action=remove_abandoned&recover_id=[TARGET_POST_ID]`\n\n## 6. Test Data Setup\nTo safely test the exploit, create a dummy post to serve as the target:\n1. Use WP-CLI to create a \"Victim\" post:\n   ```bash\n   wp post create --post_type=post --post_title=\"Victim Post\" --post_status=publish --post_content=\"This content should be deleted.\"\n   ```\n2. Note the ID of the created post (e.g., `123`).\n3. Ensure the plugin is active:\n   ```bash\n   wp plugin activate abandoned-contact-form-7\n   ```\n\n## 7. Expected Results\n- **HTTP Response:** Usually, WordPress AJAX handlers that do not explicitly return JSON or use `wp_die()` with a message will return a `200 OK` with a body of `0` or `1` (or nothing if the function terminates early).\n- **Database State:** The post with the ID provided in `recover_id` should be completely removed from the `wp_posts` table.\n\n## 8. Verification Steps\nAfter sending the exploit request, verify the deletion using WP-CLI:\n1. Attempt to retrieve the post:\n   ```bash\n   wp post get [TARGET_POST_ID]\n   ```\n2. **Expected Verification Outcome:** WP-CLI should return an error: `Error: Could not find the post with ID [TARGET_POST_ID].`\n\n## 9. Alternative Approaches\nIf the `$_POST` parameter `recover_id` is not accepted, the plugin might be reading from `$_GET` or `$_REQUEST`.\n- **Alternative 1 (GET Request):**\n  `GET \u002Fwp-admin\u002Fadmin-ajax.php?action=remove_abandoned&recover_id=[TARGET_POST_ID]`\n- **Alternative 2 (Different Parameter Name):** \n  If `recover_id` (inferred from description) fails, check the source code for other parameters passed to `wp_delete_post`. If the handler iterates through an array, try `recover_id[]=[ID]`.","The Abandoned Contact Form 7 plugin for WordPress is vulnerable to unauthenticated arbitrary post deletion in versions up to and including 2.2. This occurs due to a lack of authorization checks and nonce validation in the 'action__remove_abandoned' AJAX handler, allowing any visitor to permanently delete posts, pages, or media.","\u002F\u002F In abandoned-contact-form-7.php\nfunction action__remove_abandoned() {\n    \u002F\u002F ... (missing check_ajax_referer and current_user_can)\n    wp_delete_post( $_POST['recover_id'], true );\n    wp_die();\n}","--- abandoned-contact-form-7.php\n+++ abandoned-contact-form-7.php\n@@ -1,4 +1,9 @@\n function action__remove_abandoned() {\n+    check_ajax_referer( 'cf7af_remove_action', 'nonce' );\n+    if ( ! current_user_can( 'delete_posts' ) ) {\n+        wp_die( 'Unauthorized' );\n+    }\n+\n     $recover_id = isset( $_POST['recover_id'] ) ? intval( $_POST['recover_id'] ) : 0;\n-    wp_delete_post( $recover_id, true );\n+    if ( get_post_type( $recover_id ) === 'cf7af_data' ) {\n+        wp_delete_post( $recover_id, true );\n+    }\n     wp_die();\n }","The vulnerability is exploited by sending an unauthenticated POST request to the WordPress AJAX endpoint (\u002Fwp-admin\u002Fadmin-ajax.php). The request must include the 'action' parameter set to 'remove_abandoned' and a 'recover_id' parameter containing the ID of the target post to be deleted. Because the handler lacks permission checks and does not verify the post type, it performs a permanent deletion (bypassing the trash) of the specified ID.","gemini-3-flash-preview","2026-06-25 23:52:32","2026-06-25 23:52:58",{"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\u002Fabandoned-contact-form-7\u002Ftags"]