Spam Protect for Contact Form 7 <= 1.2.9 - Authenticated (Editor+) Arbitrary File Deletion
Description
The Spam Protect for Contact Form 7 plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in all versions up to, and including, 1.2.9. This makes it possible for authenticated attackers, with Editor-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).
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:HTechnical Details
<=1.2.9What Changed in the Fix
Changes introduced in v1.2.10
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-32496 ## 1. Vulnerability Summary The **Spam Protect for Contact Form 7** plugin (versions <= 1.2.9) is vulnerable to **Arbitrary File Deletion** due to a path traversal flaw in its log management logic. The plugin allows users to define a custom filename for …
Show full research plan
Exploitation Research Plan: CVE-2026-32496
1. Vulnerability Summary
The Spam Protect for Contact Form 7 plugin (versions <= 1.2.9) is vulnerable to Arbitrary File Deletion due to a path traversal flaw in its log management logic. The plugin allows users to define a custom filename for spam logs and provides a feature to "erase" this log file. Because the plugin insufficiently validates the file path before passing it to the PHP unlink() function, an authenticated attacker with Editor privileges or higher can delete sensitive files (like wp-config.php) by providing a malicious path such as ../wp-config.php.
2. Attack Vector Analysis
- Endpoint: WordPress Admin Panel, specifically the Contact Form 7 (CF7) editor page.
- Action/Hook:
wpcf7_after_saveaction hook, which triggers the plugin'sspcf7_plugin_save_contact_formmethod. - Vulnerable Parameter:
wpcf7_block_log_filename. - Trigger Parameter: A parameter to trigger the log erasure (inferred as
wpcf7_erase_logorwpcf7_erase_logfile). - Required Role: Authenticated Editor or higher (as they can edit CF7 forms).
- Preconditions:
- The plugin Spam Protect for Contact Form 7 must be active.
Summary
The Spam Protect for Contact Form 7 plugin for WordPress is vulnerable to arbitrary file deletion in versions up to 1.2.9 due to path traversal in its log management feature. Authenticated attackers with Editor-level access or higher can exploit this by supplying a malicious file path in the log filename parameter and triggering the log erasure functionality, potentially leading to the deletion of critical files like wp-config.php.
Vulnerable Code
// admin/class-admin.php line 273 // Log filename $wpcf7_block_log_filename = sanitize_text_field( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $_POST['wpcf7_block_log_filename'] ) ); update_post_meta($post_id, "_wpcf7_block_log_filename", trim($wpcf7_block_log_filename)); //Erase Log $erase_log = sanitize_text_field($_POST['wpcf7_block_log_erase']); if ($erase_log == "1"){ if ($wpcf7_block_log_filename != ""){ unlink("../wp-content/".$wpcf7_block_log_filename); }else{ $log_handle = fopen("../wp-content/spcf_spam_block.log", "w" ); fclose($log_handle); } }
Security Fix
@@ -83,6 +83,8 @@ $can_send_request = false; if ($wpcf7_block_log_filename != "") { $log_file_size = filesize("../wp-content/".$wpcf7_block_log_filename); }else{ $log_file_size = filesize("../wp-content/spcf_spam_block.log"); } + if (empty($wpcf7_block_log_filename)) { $wpcf7_block_log_filename = "spcf_spam_block.log"; } + $log_file_size_str = 0; if ($log_file_size > 0 && $log_file_size < 1024000){ $log_file_size_str = round($log_file_size /1024, 2)." KB"; @@ -184,8 +186,8 @@ <div class="block-error-msg"> <h3 class="blocker-7-setting second">Set your log file filename. <span><small>(optional)</small></span></h3> <p><small class="blocker-7-setting-small"> - Please specify the filename you prefer for storing the log. For instance, 'spcf_spam_block.log' (recommended), 'mylog.txt,' or '[random-secret-name].html.' <br> - You may leave this field blank to use the default value. Utilize this field to manage different log files for multiple contact forms across your site. <br> + Please specify the filename you prefer for storing the log. For instance, 'spcf_spam_block.log' (recommended), 'myform.log,' or '[random-name].log', extension must always be (.log). <br> + You may leave this field blank to use the default value 'spcf_spam_block.log'. You can utilize this field to manage different log files for multiple contact forms across your site. <br> IMPORTANT: Ensure your server supports MIME file extensions for download or viewing, and ensure the file does already exist or is being used by another plugin. </small></p> <input type="text" name="wpcf7_block_log_filename" id="wpcf7-block-log-filename-id" @@ -271,7 +273,17 @@ // Log filename $wpcf7_block_log_filename = sanitize_text_field( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $_POST['wpcf7_block_log_filename'] ) ); - update_post_meta($post_id, "_wpcf7_block_log_filename", trim($wpcf7_block_log_filename)); + // Ensure filename is not empty and ends with .log + if (!empty($wpcf7_block_log_filename)) { + // Ensure filename ends with .log + if (pathinfo($wpcf7_block_log_filename, PATHINFO_EXTENSION) !== 'log') { + $wpcf7_block_log_filename .= '.log'; + } + } else { + $wpcf7_block_log_filename = "spcf_spam_block.log"; + } + + update_post_meta($post_id, "_wpcf7_block_log_filename", trim($wpcf7_block_log_filename)); //Erase Log $erase_log = sanitize_text_field($_POST['wpcf7_block_log_erase']);
Exploit Outline
To exploit this vulnerability, an authenticated attacker with Editor privileges or higher (who has permission to edit Contact Form 7 forms) must submit a POST request to save a form's settings. This request is typically directed to wp-admin/admin.php and triggers the wpcf7_after_save hook. The attacker includes the wpcf7_block_log_filename parameter set to a path traversal string targeting a sensitive file (e.g., ../wp-config.php) and sets the wpcf7_block_log_erase parameter to 1. Because the plugin does not validate the filename for directory traversal sequences before passing it to the unlink() function, the specified file is deleted from the server.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.