CVE-2026-1540

Spam Protect for Contact Form 7 < 1.2.10 - Authenticated (Editor+) Remote Code Execution

highImproper Control of Generation of Code ('Code Injection')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
1.2.10
Patched in
35d
Time to patch

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

Technical Details

Affected versions<1.2.10
PublishedMarch 12, 2026
Last updatedApril 15, 2026

What Changed in the Fix

Changes introduced in v1.2.10

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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 like your-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

  1. Setting Definition: In admin/class-admin.php, the plugin registers an "Antispam Settings" tab for CF7.
  2. Metadata Storage: When the "Save" button is clicked in the CF7 editor, the wpcf7_after_save hook calls spcf7_plugin_save_contact_form (inferred). This function saves the _wpcf7_block_log_filename meta key.
  3. Log Check: The spcf7_plugin_admin_post_settings function in admin/class-admin.php retrieves this filename and checks its size using:
    filesize("../wp-content/".$wpcf7_block_log_filename). (Line 92).
  4. 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.
  5. 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/.
  6. Sink: The log entry, including the submitted "message" or "IP", is written to wp-content/shell.php via fopen/fwrite or file_put_contents.

4. Nonce Acquisition Strategy

To update the plugin settings, the attacker must submit a POST request to the CF7 save

Research Findings
Static analysis — not yet PoC-verified

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

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wp-contact-form-7-spam-blocker/1.2.9/admin/class-admin.php /home/deploy/wp-safety.org/data/plugin-versions/wp-contact-form-7-spam-blocker/1.2.10/admin/class-admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/wp-contact-form-7-spam-blocker/1.2.9/admin/class-admin.php	2025-08-16 18:17:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-contact-form-7-spam-blocker/1.2.10/admin/class-admin.php	2026-02-06 21:29:26.000000000 +0000
@@ -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.