CVE-2026-0811

Advanced CF7 DB <= 2.0.9 - Cross-Site Request Forgery to Form Entry Deletion

mediumCross-Site Request Forgery (CSRF)
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
2.1.0
Patched in
1d
Time to patch

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:L
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
None
Confidentiality
Low
Integrity
Low
Availability

Technical Details

Affected versions<=2.0.9
PublishedApril 8, 2026
Last updatedApril 8, 2026
Affected pluginadvanced-cf7-db

What Changed in the Fix

Changes introduced in v2.1.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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:
    1. wp-admin/admin.php?page=contact-form-listing (Bulk/Single entry deletion)
    2. wp-admin/admin-ajax.php (AJAX settings or bulk actions)
  • Vulnerable Action: Deleting form entries via the action=delete parameter.
  • 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;
}
  1. An administrator accesses the plugin's listing page (page=contact-form-listing).
  2. The code generates a new nonce for the action vsz-cf7-action-nonce and stores it in $nonce.
  3. It then calls wp_verify_nonce($nonce, ...) on the variable it just created. This check always passes and completely ignores the _wpnonce parameter in $_POST or $_GET.
  4. The script continues to process state-changing parameters like action=delete and data_id[].
  5. 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

  1. Identify Target: Determine the Form ID (cf7_id) and the Entry ID (data_id) to delete.
  2. Craft Payload: A POST request to the listing page containing the deletion action.
  3. Execution: Use http_request to 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: delete
    • data_id[]: [ENTRY_ID]
    • _wpnonce: anything (ignored due to the flaw)

6. Test Data Setup

  1. Ensure CF7 is active: Contact Form 7 must be installed and active.
  2. Create a Form: Ensure at least one form exists (default is usually ID 1).
  3. Generate an Entry:
    • Use wp post list --post_type=wpcf7_contact_form to 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"
      
  4. 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_id should be purged from the database.

8. Verification Steps

  1. Database Check: After the exploit, verify the entry is gone.
    wp db query "SELECT COUNT(*) FROM wp_cf7_vdata_entry WHERE data_id = [ENTRY_ID]"
    
    A result of 0 confirms successful deletion.
  2. UI Check: Use browser_navigate to wp-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]&
Research Findings
Static analysis — not yet PoC-verified

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

--- /home/deploy/wp-safety.org/data/plugin-versions/advanced-cf7-db/2.0.9/admin/class-advanced-cf7-db-admin.php	2025-02-06 12:14:44.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/advanced-cf7-db/2.1.0/admin/class-advanced-cf7-db-admin.php	2026-04-02 12:45:36.000000000 +0000
@@ -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.