Advanced CF7 DB <= 2.0.9 - Cross-Site Request Forgery to Form Entry Deletion
Description
The Advanced Contact form 7 DB plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 2.0.9. This is due to missing or incorrect nonce validation on the 'vsz_cf7_save_setting_callback' function. This makes it possible for unauthenticated attackers to delete form entry via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:LTechnical Details
<=2.0.9What Changed in the Fix
Changes introduced in v2.1.0
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-0811 (Advanced CF7 DB) ## 1. Vulnerability Summary The **Advanced Contact form 7 DB** plugin (up to 2.0.9) is vulnerable to **Cross-Site Request Forgery (CSRF)** because it implements a flawed nonce validation pattern in several admin handlers, including the e…
Show full research plan
Exploitation Research Plan: CVE-2026-0811 (Advanced CF7 DB)
1. Vulnerability Summary
The Advanced Contact form 7 DB plugin (up to 2.0.9) is vulnerable to Cross-Site Request Forgery (CSRF) because it implements a flawed nonce validation pattern in several admin handlers, including the entry management screen (admin/partials/contact_form_listing.php) and the inferred vsz_cf7_save_setting_callback function.
The developer attempted to implement security by creating a nonce and immediately verifying it against itself (a "no-op" check), which effectively ignores any nonce provided in the HTTP request. This allows an unauthenticated attacker to trick a logged-in administrator into performing actions like deleting form entries.
2. Attack Vector Analysis
- Vulnerable Endpoints:
wp-admin/admin.php?page=contact-form-listing(Bulk/Single entry deletion)wp-admin/admin-ajax.php(AJAX settings or bulk actions)
- Vulnerable Action: Deleting form entries via the
action=deleteparameter. - Authentication Level: Unauthenticated (Attacker) / Administrator (Victim).
- Preconditions:
- The plugin must have at least one Contact Form 7 form configured.
- There must be at least one saved entry in the database.
- The attacker must know (or guess) the Form ID (
cf7_id) and Entry ID (data_id).
3. Code Flow
The vulnerability stems from a repetitive coding error found in multiple partials:
File: admin/partials/contact_form_listing.php (Lines 36-41)
$nonce = wp_create_nonce('vsz-cf7-action-nonce');
if(!wp_verify_nonce( $nonce, 'vsz-cf7-action-nonce')){
echo esc_html('You have no permission to access this page');
return;
}
- An administrator accesses the plugin's listing page (
page=contact-form-listing). - The code generates a new nonce for the action
vsz-cf7-action-nonceand stores it in$nonce. - It then calls
wp_verify_nonce($nonce, ...)on the variable it just created. This check always passes and completely ignores the_wpnonceparameter in$_POSTor$_GET. - The script continues to process state-changing parameters like
action=deleteanddata_id[]. - Because the CSRF protection is non-functional, a forged request from the admin's browser triggers the deletion logic.
4. Nonce Acquisition Strategy
No nonce is required.
Although the plugin generates nonces (e.g., vsz-cf7-action-nonce), the validation logic is flawed (self-verifying). An attacker does not need to obtain a valid nonce to bypass the check. Simply omitting the nonce or providing a dummy value will work because the server-side code does not check the request's nonce parameter against its expected value.
5. Exploitation Strategy
Goal: Delete a specific form entry via CSRF
- Identify Target: Determine the Form ID (
cf7_id) and the Entry ID (data_id) to delete. - Craft Payload: A POST request to the listing page containing the deletion action.
- Execution: Use
http_requestto simulate the administrator's browser submitting the form.
HTTP Request (Bulk Delete Action):
- URL:
http://[target]/wp-admin/admin.php?page=contact-form-listing&cf7_id=[FORM_ID] - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body Parameters:
action:deletedata_id[]:[ENTRY_ID]_wpnonce:anything(ignored due to the flaw)
6. Test Data Setup
- Ensure CF7 is active: Contact Form 7 must be installed and active.
- Create a Form: Ensure at least one form exists (default is usually ID 1).
- Generate an Entry:
- Use
wp post list --post_type=wpcf7_contact_formto find a form ID. - Simulate a form submission to populate the database:
# Example submission to Form ID 1 curl -X POST http://localhost:8080/wp-json/contact-form-7/v1/contact-forms/1/feedback \ -F "your-name=TargetUser" -F "your-email=target@example.com" -F "your-message=DeleteMe"
- Use
- Identify the Entry ID:
wp db query "SELECT data_id FROM wp_cf7_vdata_entry ORDER BY data_id DESC LIMIT 1"
7. Expected Results
- The HTTP response from the admin page should load without the "You have no permission" error.
- The entry associated with the
data_idshould be purged from the database.
8. Verification Steps
- Database Check: After the exploit, verify the entry is gone.
A result ofwp db query "SELECT COUNT(*) FROM wp_cf7_vdata_entry WHERE data_id = [ENTRY_ID]"0confirms successful deletion. - UI Check: Use
browser_navigatetowp-admin/admin.php?page=contact-form-listing&cf7_id=[FORM_ID]and verify the record is no longer visible in the table.
9. Alternative Approaches
If the bulk action requires specific form state, try the AJAX settings callback mentioned in the CVE:
- Action:
vsz_cf7_save_setting - Endpoint:
/wp-admin/admin-ajax.php - Parameters: `action=vsz_cf7_save_setting&cf7_id=[ID]&
Summary
The Advanced Contact form 7 DB plugin for WordPress is vulnerable to Cross-Site Request Forgery (CSRF) due to a flawed security implementation where nonces are created and immediately verified against themselves rather than validating the user's request. This allows unauthenticated attackers to trick administrators into deleting form entries or modifying plugin settings via forged requests.
Vulnerable Code
// admin/partials/contact_form_listing.php lines 36-41 $nonce = wp_create_nonce('vsz-cf7-action-nonce'); if(!wp_verify_nonce( $nonce, 'vsz-cf7-action-nonce')){ echo esc_html('You have no permission to access this page'); return; } --- // admin/class-advanced-cf7-db-admin.php lines 881-887 if($current_action == 'delete'){ if(isset($_POST['del_id']) && !empty($_POST['del_id'])){ //Get nonce value $nonce = sanitize_text_field($_POST['_wpnonce']); //Verify nonce value // if(!wp_verify_nonce($nonce, 'vsz-cf7-action-nonce')) { // die('Security check'); // }
Security Fix
@@ -881,16 +883,19 @@ if($current_action == 'delete'){ if(isset($_POST['del_id']) && !empty($_POST['del_id'])){ //Get nonce value - $nonce = sanitize_text_field($_POST['_wpnonce']); + if(!isset($_POST['_wpnonce']) || empty($_POST['_wpnonce'])){ + wp_die(__('Security check failed: Missing nonce.')); + } + $nonce = sanitize_text_field(wp_unslash($_POST['_wpnonce'])); //Verify nonce value - // if(!wp_verify_nonce($nonce, 'vsz-cf7-action-nonce')) { - // die('Security check'); - // } + if(!wp_verify_nonce($nonce, 'vsz-cf7-action-nonce')) { + wp_die(__('Security check failed: Invalid nonce.')); + } //Get Delete row ID information - $del_id = array_map('sanitize_text_field',$_POST['del_id']); + $del_id = array_map('sanitize_text_field', wp_unslash($_POST['del_id'])); $del_id = implode(',', array_map('intval',$del_id)); //Get Form ID - $fid = intval(sanitize_text_field($_POST['fid'])); + $fid = intval(sanitize_text_field(wp_unslash($_POST['fid'])));
Exploit Outline
The exploit targets the entry management screen to delete saved form data. An attacker crafts a POST request to 'wp-admin/admin.php?page=contact-form-listing' including the parameters 'action=delete', 'cf7_id=[FORM_ID]', and an array of entry IDs in 'del_id[]'. Because the plugin either comments out the nonce verification or performs a 'no-op' verification (comparing a newly generated nonce to itself), the attacker does not need to provide a valid nonce. The attacker then tricks a logged-in administrator into triggering this request (e.g., via a hidden form on a malicious site), resulting in the deletion of specified database records.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.