Database for Contact Form 7, WPforms, Elementor forms <= 1.5.1 - Unauthenticated Arbitrary File Deletion via CF7 File Field POST Value
Description
The Database for Contact Form 7, WPforms, Elementor forms plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in the view_page function in all versions up to, and including, 1.5.1. This makes it possible for unauthenticated attackers 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). Successful exploitation requires an administrator to view or edit the poisoned form entry, at which point PHP's bracket parser reshapes the attacker-crafted JSON key to bypass the stored-path isset check and trigger deletion of the traversal-specified file.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:HTechnical Details
<=1.5.1What Changed in the Fix
Changes introduced in v1.5.2
Source Code
WordPress.org SVNThis research plan focuses on **CVE-2026-9843**, a path traversal vulnerability in the "Database for Contact Form 7" plugin that allows for arbitrary file deletion. ### 1. Vulnerability Summary The "Database for Contact Form 7, WPforms, Elementor forms" plugin (versions <= 1.5.1) fails to properly …
Show full research plan
This research plan focuses on CVE-2026-9843, a path traversal vulnerability in the "Database for Contact Form 7" plugin that allows for arbitrary file deletion.
1. Vulnerability Summary
The "Database for Contact Form 7, WPforms, Elementor forms" plugin (versions <= 1.5.1) fails to properly validate file paths stored in form entries. An unauthenticated attacker can submit a contact form with a specially crafted field name containing path traversal sequences (e.g., ../../../../wp-config.php).
When an administrator later views or edits this poisoned entry in the WordPress dashboard, the plugin's view_page functionality processes the entry data. Due to how PHP's bracket parser handles nested array keys in $_POST (reshaping them), an attacker can bypass isset() checks intended to verify that a file belongs to the entry. This allows the attacker to trigger the deletion (unlink) of any file the web server has permissions to delete.
2. Attack Vector Analysis
- Target Endpoint: Public-facing contact forms (Contact Form 7, WPForms, or Elementor) integrated with the plugin.
- Submission Endpoint (CF7 Example):
/wp-json/contact-form-7/v1/contact-forms/<ID>/feedback - Trigger Endpoint (Admin):
wp-admin/admin.php?page=vxcf_leads&action=edit&id=<Entry_ID> - Vulnerable Parameter: The key of a POST parameter intended for file uploads (e.g.,
vx_file[path/to/file]). - Preconditions:
- A contact form must be active on the site.
- An administrator must view or update the malicious entry in the plugin's dashboard.
3. Code Flow
- Submission:
vxcf_form::create_entry_cf()(or similar for other form plugins) is triggered via thewpcf7_before_send_mailhook. - Storage: The plugin iterates over
$_POSTand$_FILES. It saves the submission data, including the attacker's crafted keys, into thewp_vxcf_leadstable (or similar) as serialized data or JSON. - Admin Interaction: An administrator navigates to the "CRM Entries" page and selects the poisoned entry.
- Processing: The
vxcf_form_pages::view_page()(inferred) function is called. It retrieves the stored fields. - Sink: If the admin "Updates" the entry or triggers a "Delete File" action, the plugin compares the
POSTdata against the stored fields. The "bracket parser" reshaping allows a manipulated$_POSTkey to be treated as a valid file path from the entry, which is then passed tounlink().
4. Nonce Acquisition Strategy
- Unauthenticated Submission: Contact Form 7 often requires a REST API nonce (
_wpcf7_unit_tagand potentially a nonce in headers), but it is usually available to anonymous users by fetching the page containing the form. - Admin Interaction: Accessing the admin dashboard requires standard session cookies. The "Update" or "Delete" actions in the admin panel will be protected by a WordPress nonce.
- Action Name:
vx_crm_ajax(for AJAX actions) or standard admin nonces. - JS Variable: Check
window.vxcf_leads_dataor similar localized scripts fornoncevalues.
- Action Name:
5. Exploitation Strategy
- Environment Setup: Create a dummy file to delete:
wp-content/pwn.txt. - Reconnaissance:
- Identify an active Contact Form 7 form ID by navigating to the homepage.
- Note the form's required fields (name, email, etc.).
- Poisoning (Unauthenticated):
- Submit a POST request to the CF7 endpoint.
- Payload: Include a parameter like
vxcf_file[../../../../wp-content/pwn.txt]=1.
- Triggering (Authenticated):
- Log in as an administrator.
- Navigate to
wp-admin/admin.php?page=vxcf_leads. - Identify the ID of the new entry.
- Navigate to the Edit page:
wp-admin/admin.php?page=vxcf_leads&action=edit&id=<ID>. - Perform an "Update" or trigger the file removal logic.
- Verification: Check if
wp-content/pwn.txtstill exists.
6. Test Data Setup
- Plugin Configuration: Ensure "Contact Form Entries" is active and CF7 is installed.
- Target File:
touch /var/www/html/wp-content/pwn.txt - Shortcode Page: Create a page with a form if none exists:
wp post create --post_type=page --post_title="Contact" --post_status=publish --post_content='[contact-form-7 id="FORM_ID"]'
7. Expected Results
- The unauthenticated submission should return a
200 OKstatus with a "mail_sent" or "validation_failed" response (the plugin saves data even if mail fails). - The admin viewing/updating the entry should result in the server calling
unlink()on the path provided in the bracketed key. - The file
wp-content/pwn.txtshould be deleted from the filesystem.
8. Verification Steps (Post-Exploit)
# Check if the entry was saved in the database
wp db query "SELECT * FROM wp_vxcf_leads ORDER BY id DESC LIMIT 1;"
# Check if the file was deleted
ls /var/www/html/wp-content/pwn.txt
# Expected: "ls: cannot access ... No such file or directory"
9. Alternative Approaches
If the view_page direct trigger fails, investigate the ajax_actions function in includes/plugin-pages.php. There may be a delete_file action accessible via admin-ajax.php.
- Payload for AJAX:
action=actions_vxcf_leads&action2=delete_file&entry_id=<ID>&file_name=../../../../wp-content/pwn.txt - This would require capturing the
vx_crm_ajaxnonce first.
Summary
The 'Database for Contact Form 7' plugin allows unauthenticated attackers to delete arbitrary files on the server (e.g., wp-config.php) via path traversal. This occurs because the plugin stores attacker-supplied file paths from form submissions and subsequently calls unlink() on those paths without validation when an administrator views or updates the entry.
Vulnerable Code
// includes/plugin-pages.php lines 1188-1200 if(is_array($db_files)){ foreach($db_files as $k=>$file){ if(!isset($_POST['files_'.$name][$k])){ //delete old file if( file_exists($upload['dir'].$file)){ @unlink($upload['dir'].$file); } }else{ $files[]=$file; } }
Security Fix
Exploit Outline
1. **Unauthenticated Submission:** The attacker identifies a Contact Form 7, WPForms, or Elementor form on the target site and submits a POST request. 2. **Path Traversal Payload:** The submission includes a field key designed to exploit PHP's bracket parsing, such as `vx_file[../../../../wp-config.php]`. The plugin stores this raw path in the database as a file attachment. 3. **Administrative Trigger:** An administrator logs into the WordPress dashboard and navigates to the 'CRM Entries' page to view or edit the specific submission. 4. **Execution:** When the administrator performs an update action, the plugin checks if the 'files' stored in the database are present in the current `$_POST` request. Because the attacker's path-based key is not present in the admin's legitimate update request, the plugin assumes the file was deleted by the user and executes `unlink()` on the traversal path, deleting the target file.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.