Spam Protect for Contact Form 7 < 1.2.10 - Authenticated (Editor+) Remote Code Execution
Description
The Spam Protect for Contact Form 7 plugin for WordPress is vulnerable to Remote Code Execution in all versions up to 1.2.10 (exclusive). This makes it possible for authenticated attackers, with Editor-level access and above, to execute code on the server.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<1.2.10What Changed in the Fix
Changes introduced in v1.2.10
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-1540 ## 1. Vulnerability Summary The **Spam Protect for Contact Form 7** plugin (up to version 1.2.9) is vulnerable to **Remote Code Execution (RCE)** via an arbitrary file write/injection vulnerability. The plugin allows users with Editor-level permissions (…
Show full research plan
Exploitation Research Plan - CVE-2026-1540
1. Vulnerability Summary
The Spam Protect for Contact Form 7 plugin (up to version 1.2.9) is vulnerable to Remote Code Execution (RCE) via an arbitrary file write/injection vulnerability. The plugin allows users with Editor-level permissions (or higher) to define a custom filename for spam logs. Because the plugin does not restrict the file extension or sanitize the file path, an attacker can specify a .php filename. When the plugin logs a blocked spam attempt, it writes submitted form data (which can contain PHP code) into the specified file, leading to server-side code execution.
2. Attack Vector Analysis
- Endpoint: The Contact Form 7 (CF7) editor and the public form submission endpoint.
- Hook:
wpcf7_after_save(triggered when saving CF7 settings) and CF7 submission validation hooks (triggered on form submission). - Vulnerable Parameter:
wpcf7_block_log_filename(settings) and form fields likeyour-message(injection). - Authentication: Authenticated Editor+ level access is required to modify the settings. Unauthenticated access is sufficient to trigger the log entry (and thus the RCE) once the setting is configured.
- Preconditions:
- Contact Form 7 must be installed and active.
- A contact form must exist.
3. Code Flow
- Setting Definition: In
admin/class-admin.php, the plugin registers an "Antispam Settings" tab for CF7. - Metadata Storage: When the "Save" button is clicked in the CF7 editor, the
wpcf7_after_savehook callsspcf7_plugin_save_contact_form(inferred). This function saves the_wpcf7_block_log_filenamemeta key. - Log Check: The
spcf7_plugin_admin_post_settingsfunction inadmin/class-admin.phpretrieves this filename and checks its size using:filesize("../wp-content/".$wpcf7_block_log_filename). (Line 92). - Log Writing: When a user submits a CF7 form, the blocker logic (in
includes/class-blocker.php) checks if the submission is spam based on the saved settings. - Trigger: If a blocked value (e.g., a specific email) is used, the plugin calls a logging function. This function uses the
_wpcf7_block_log_filename(e.g.,shell.php) and prepends../wp-content/. - Sink: The log entry, including the submitted "message" or "IP", is written to
wp-content/shell.phpviafopen/fwriteorfile_put_contents.
4. Nonce Acquisition Strategy
To update the plugin settings, the attacker must submit a POST request to the CF7 save
Summary
The Spam Protect for Contact Form 7 plugin allows authenticated users with Editor-level permissions to set a custom log filename without extension validation. An attacker can set the log filename to a .php file, then trigger a spam-blocked form submission containing a PHP payload, which is subsequently written to the log file in the wp-content directory, resulting in Remote Code Execution.
Vulnerable Code
// admin/class-admin.php L271 // 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)); --- // admin/class-admin.php L92 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"); }
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 not 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 attacker with Editor-level access or higher must first modify the Antispam Settings for a Contact Form 7 instance. The attacker updates the `wpcf7_block_log_filename` setting to a PHP filename (e.g., `shell.php`). Then, the attacker or an unauthenticated user submits a form that triggers a spam block (for example, by including a blacklisted word). In this submission, the attacker includes a malicious PHP payload (e.g., `<?php system($_GET['cmd']); ?>`) in one of the form fields. The plugin writes this submission data into the specified log file at `wp-content/shell.php`, which the attacker can then access directly to execute code.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.