CVE-2025-14457

Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.2 - Missing Authorization to Unauthenticated File Deletion

lowMissing Authorization
3.7
CVSS Score
3.7
CVSS Score
low
Severity
1.3.9.3
Patched in
1d
Time to patch

Description

The Drag and Drop Multiple File Upload for Contact Form 7 plugin for WordPress is vulnerable to unauthorized modification of data due to a missing ownership check in the dnd_codedropz_upload_delete() function in all versions up to, and including, 1.3.9.2. This makes it possible for unauthenticated attackers to delete arbitrary uploaded files when the "Send attachments as links" setting is enabled.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.3.9.2
PublishedJanuary 14, 2026
Last updatedJanuary 15, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-14457 ## 1. Vulnerability Summary The **Drag and Drop Multiple File Upload for Contact Form 7** plugin (<= 1.3.9.2) contains a missing authorization vulnerability in its AJAX handler `dnd_codedropz_upload_delete()`. While the function performs a nonce check, i…

Show full research plan

Exploitation Research Plan: CVE-2025-14457

1. Vulnerability Summary

The Drag and Drop Multiple File Upload for Contact Form 7 plugin (<= 1.3.9.2) contains a missing authorization vulnerability in its AJAX handler dnd_codedropz_upload_delete(). While the function performs a nonce check, it fails to verify the ownership or "session-boundedness" of the file being deleted. When the plugin setting "Send attachments as links" is enabled, uploaded files are stored on the server. An unauthenticated attacker can obtain a valid nonce from the frontend and subsequently delete arbitrary files within the plugin's upload directory by predicting or obtaining their filenames.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: dnd_codedropz_upload_delete
  • Method: POST
  • Authentication: Unauthenticated (via wp_ajax_nopriv_ hook)
  • Vulnerable Parameter: file (the filename/path to be deleted)
  • Precondition: The "Send attachments as links" option must be enabled in the Contact Form 7 "Drag and Drop Upload" settings.

3. Code Flow

  1. Registration: The plugin registers the AJAX actions in the main plugin file or an initialization class:
    add_action( 'wp_ajax_dnd_codedropz_upload_delete', 'dnd_codedropz_upload_delete' );
    add_action( 'wp_ajax_nopriv_dnd_codedropz_upload_delete', 'dnd_codedropz_upload_delete' );
    
  2. Entry Point: dnd_codedropz_upload_delete() in inc/ajax-functions.php (or similar) is invoked.
  3. Nonce Verification: It calls check_ajax_referer( 'dnd_codedropz_upload_nonce', 'nonce' ).
  4. Processing:
    • It retrieves the filename from $_POST['file'].
    • It constructs the file path based on the plugin's upload directory (typically wp-content/uploads/wpcf7_drag-n-drop_uploads/tmp/ or similar).
  5. Sink: The code calls unlink( $file_path ) or wp_delete_attachment() without checking if the current requester is the one who uploaded the file.

4. Nonce Acquisition Strategy

The plugin exposes the required nonce to unauthenticated users on any page where a Contact Form 7 form with the "Drag and Drop" field is present.

  1. Identify Shortcode: The plugin's field is added to CF7 using the [drag-and-drop-file] tag.
  2. Create Test Page:
    • Create a CF7 form containing [drag-and-drop-file file-limit:10 "upload-field"].
    • Create a WordPress page with the shortcode for that form: [contact-form-7 id="XX" title="Test Form"].
  3. Extract Nonce via Browser:
    • Navigate to the page.
    • The plugin localizes data into a JavaScript object, typically dnd_cf7_uploader.
    • JS Variable: dnd_cf7_uploader.ajax_nonce or dnd_cf7_uploader.nonce.
    • Execution Command: browser_eval("window.dnd_cf7_uploader?.ajax_nonce").

5. Exploitation Strategy

  1. Preparation:
    • Identify/Create a file to delete. In a real scenario, the attacker would first upload a file (which returns the filename) or guess the names of files uploaded by others.
    • Obtain the dnd_codedropz_upload_nonce using the strategy in Section 4.
  2. Execute Deletion:
    • Send a POST request to admin-ajax.php.
    • URL: http://<target>/wp-admin/admin-ajax.php
    • Body (URL-encoded):
      action=dnd_codedropz_upload_delete&nonce=<NONCE>&file=<TARGET_FILENAME>
      
    • Note: The file parameter might require just the basename or a relative path depending on the exact plugin version implementation.

6. Test Data Setup

  1. Install/Activate: Contact Form 7 and Drag and Drop Multiple File Upload for Contact Form 7 (<= 1.3.9.2).
  2. Configure Plugin:
    • Go to CF7 -> Drag and Drop Upload.
    • Ensure "Send attachments as links" is checked.
  3. Create Form:
    • Add a form with [drag-and-drop-file drag-upload-1].
    • Place form shortcode on a public page /test-upload-page/.
  4. Create Target File:
    • Manually upload a file via the form or place a file in wp-content/uploads/wpcf7_drag-n-drop_uploads/ named secret-data.txt.

7. Expected Results

  • The server should return a 200 OK response (likely with a JSON success message or 1).
  • The file wp-content/uploads/wpcf7_drag-n-drop_uploads/secret-data.txt (or the tmp/ subdirectory) will be deleted from the filesystem.

8. Verification Steps

  1. Filesystem Check: Use WP-CLI or shell to verify the file is gone.
    ls /var/www/html/wp-content/uploads/wpcf7_drag-n-drop_uploads/secret-data.txt
    
    • Expected Result: ls: cannot access ...: No such file or directory.

9. Alternative Approaches

  • Path Traversal: Check if the file parameter is vulnerable to path traversal (e.g., ../../wp-config.php). The unlink sink is particularly dangerous if the plugin doesn't use basename() on the input.
  • Attachment Deletion: If the plugin uses wp_delete_attachment( $id ), attempt to pass an integer file ID of a legitimate site attachment (e.g., a header image) to test for broader unauthorized deletion.
  • Directory Guessing: If the filename includes a hash or timestamp, attempt to find a leakage point in the CF7 submission logs or email if "Send as links" is active.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Drag and Drop Multiple File Upload for Contact Form 7 plugin allows unauthenticated attackers to delete arbitrary files in the plugin's temporary upload directory. This occurs because the AJAX handler for file deletion performs a nonce check but fails to verify if the requester is the owner of the file, particularly when the 'Send attachments as links' setting is enabled.

Vulnerable Code

// inc/ajax-functions.php (approximate location based on plugin structure)
add_action( 'wp_ajax_dnd_codedropz_upload_delete', 'dnd_codedropz_upload_delete' );
add_action( 'wp_ajax_nopriv_dnd_codedropz_upload_delete', 'dnd_codedropz_upload_delete' );

function dnd_codedropz_upload_delete() {
    // Only verifies the nonce, not the user's authority over the specific file
    check_ajax_referer( 'dnd_codedropz_upload_nonce', 'nonce' );

    $file = isset( $_POST['file'] ) ? sanitize_text_field( $_POST['file'] ) : '';
    $upload_dir = wp_upload_dir();
    $file_path = $upload_dir['basedir'] . '/wpcf7_drag-n-drop_uploads/tmp/' . $file;

    if ( file_exists( $file_path ) ) {
        unlink( $file_path );
    }
    wp_die();
}

Security Fix

--- a/inc/ajax-functions.php
+++ b/inc/ajax-functions.php
@@ -10,6 +10,13 @@
     check_ajax_referer( 'dnd_codedropz_upload_nonce', 'nonce' );
 
     $file = isset( $_POST['file'] ) ? sanitize_text_field( $_POST['file'] ) : '';
+    
+    // Verify that the file to be deleted belongs to the current session
+    $session_files = isset($_SESSION['dnd_uploaded_files']) ? $_SESSION['dnd_uploaded_files'] : array();
+    if ( ! in_array( $file, $session_files ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized' ) );
+        wp_die();
+    }
+
     $upload_dir = wp_upload_dir();
     $file_path = $upload_dir['basedir'] . '/wpcf7_drag-n-drop_uploads/tmp/' . $file;

Exploit Outline

The exploit target is the `dnd_codedropz_upload_delete` AJAX action. An unauthenticated attacker first navigates to any public page containing a form with the 'Drag and Drop' field to extract a valid `dnd_codedropz_upload_nonce` from the localized `dnd_cf7_uploader` JavaScript object. The attacker then identifies a target filename within the plugin's temporary upload directory (either by uploading a file themselves or predicting filenames). Finally, the attacker sends a POST request to `wp-admin/admin-ajax.php` with the `action` set to `dnd_codedropz_upload_delete`, providing the acquired nonce and the target filename in the `file` parameter, causing the server to delete the file from the filesystem.

Check if your site is affected.

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