Easy Digital Downloads <= 3.6.2 - Unvalidated Redirect in Password Reset Flow via edd_redirect
Description
The Easy Digital Downloads plugin for WordPress is vulnerable to Unvalidated Redirect in all versions up to, and including, 3.6.2. This is due to insufficient validation on the redirect url supplied via the 'edd_redirect' parameter. This makes it possible for unauthenticated attackers to redirect users with the password reset email to potentially malicious sites if they can successfully trick them into performing an action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:NTechnical Details
<=3.6.2Source Code
WordPress.org SVN# Research Plan: CVE-2025-14783 Unvalidated Redirect in Easy Digital Downloads ## 1. Vulnerability Summary Easy Digital Downloads (EDD) versions up to and including 3.6.2 are vulnerable to an unvalidated redirect. This occurs because the plugin accepts a user-supplied URL via the `edd_redirect` par…
Show full research plan
Research Plan: CVE-2025-14783 Unvalidated Redirect in Easy Digital Downloads
1. Vulnerability Summary
Easy Digital Downloads (EDD) versions up to and including 3.6.2 are vulnerable to an unvalidated redirect. This occurs because the plugin accepts a user-supplied URL via the edd_redirect parameter during the password reset flow and passes it directly to a redirection function (likely wp_redirect) without verifying if the domain is local or safe. An attacker can use this to craft a password reset link that, once used by a victim, redirects them to an external, potentially malicious site.
2. Attack Vector Analysis
- Endpoint: The password reset processing handler. In EDD, this is typically handled via an action hook like
template_redirector a specific AJAX/POST handler for form submissions. - Parameter:
edd_redirect. - Authentication: Unauthenticated (Password reset flows are accessible to any user who knows a username/email).
- Preconditions: The site must have the EDD password reset functionality active, typically via the
[edd_password_reset]shortcode.
3. Code Flow (Inferred)
Based on common EDD patterns and the vulnerability description:
- Entry Point: A user submits the password reset form or clicks a reset link.
- Processing: EDD's form processing logic (likely in
includes/user-functions.phporincludes/process-forms.php) triggers. - Redirection Logic:
- The code checks for the presence of
$_REQUEST['edd_redirect']or$_POST['edd_redirect']. - The plugin likely uses
wp_redirect( $redirect_url )instead of the more securewp_safe_redirect().
- The code checks for the presence of
- Sink: The
Locationheader is set to the unvalidated external URL.
4. Nonce Acquisition Strategy
EDD usually protects its forms with nonces. To exploit this via a form submission, we must first obtain a valid nonce from the password reset page.
- Identify Shortcode: The standard EDD password reset shortcode is
[edd_password_reset]. - Setup Test Page:
wp post create --post_type=page --post_title="Reset Password" --post_status=publish --post_content='[edd_password_reset]' - Navigate and Extract:
- Navigate to the newly created page (e.g.,
/reset-password/). - EDD often localizes its scripts. Check for a global object like
edd_scripts_varsoredd_vars. - Alternatively, inspect the HTML form for a hidden input field named
edd_login_nonceoredd_password_nonce. - Browser Eval Command:
// Check for common EDD nonce locations in the DOM document.querySelector('input[name="edd_password_nonce"]')?.value || document.querySelector('input[name="_wpnonce"]')?.value
- Navigate to the newly created page (e.g.,
5. Exploitation Strategy
We will attempt to trigger the redirect by submitting a password reset request (or completing one) with the edd_redirect parameter set to an external domain.
Step 1: Discover the Processing Action
Search the codebase for the handler of edd_redirect in the context of password resets:
grep -rn "edd_redirect" /var/www/html/wp-content/plugins/easy-digital-downloads/ | grep "wp_redirect"
Step 2: Trigger Redirect via POST
Assuming the handler is triggered by a POST request to the password reset page:
HTTP Request:
- Method:
POST - URL:
http://localhost:8080/reset-password/(or the URL of the page containing the shortcode) - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
edd_action=reset_password& edd_user_login=admin& edd_redirect=https://evil.com& edd_password_nonce=[NONCE_FROM_STEP_4]
Step 3: Trigger Redirect via GET (Alternative)
Some redirect parameters in EDD are processed via template_redirect on GET requests.
HTTP Request:
- Method:
GET - URL:
http://localhost:8080/reset-password/?edd_action=reset_password&edd_redirect=https://evil.com
6. Test Data Setup
- Install and activate Easy Digital Downloads.
- Create a standard subscriber user for testing the reset flow:
wp user create victim victim@example.com --role=subscriber - Create the reset page:
wp post create --post_type=page --post_title="Password Reset" --post_status=publish --post_content='[edd_password_reset]'
7. Expected Results
- The server should respond with a
302 Foundstatus code. - The
Locationheader in the response must be exactlyhttps://evil.com. - If the vulnerability is present,
wp_safe_redirect(which would normally prepend the site URL to an external path or default to home) will NOT have been used.
8. Verification Steps
After performing the HTTP request:
- Check Headers: Verify the
Locationheader using thehttp_requestoutput. - Code Inspection (Post-Exploit): Confirm the fix in version 3.6.3:
# Check if wp_safe_redirect is now used where edd_redirect was handled grep -rn "edd_redirect" /var/www/html/wp-content/plugins/easy-digital-downloads/
9. Alternative Approaches
If the simple POST/GET to the page doesn't work:
- Check
edd_process_reset_password_formAction: Look for where this function is defined and see if it usesedd_redirectafter sending the reset email. - AJAX Handler: Check if EDD uses an AJAX action for the "Lost Password" request:
- Action:
edd_user_back_to_loginor similar. - Search:
grep -r "wp_ajax" . | grep "password"
- Action:
- Password Reset Completion: The vulnerability might reside in the final step of the reset (where the user sets the new password). This would require a valid password reset key (
edd_keyandedd_login) generated by the system.
Summary
Easy Digital Downloads versions up to 3.6.2 are vulnerable to an unvalidated redirect in the password reset flow. The plugin accepts a user-controlled URL via the 'edd_redirect' parameter and uses it in a redirection call without proper validation, allowing attackers to redirect users to arbitrary external malicious sites.
Security Fix
@@ -102,7 +102,7 @@ if ( ! empty( $_REQUEST['edd_redirect'] ) ) { - $redirect = $_REQUEST['edd_redirect']; + $redirect = wp_validate_redirect( $_REQUEST['edd_redirect'], edd_get_current_page_url() ); } else { $redirect = edd_get_current_page_url(); } - wp_redirect( $redirect ); + wp_safe_redirect( $redirect ); exit;
Exploit Outline
1. Identify the URL of the password reset page on the target site, which typically contains the '[edd_password_reset]' shortcode. 2. Access the page as an unauthenticated user and extract the value of the 'edd_password_nonce' hidden input field. 3. Construct a POST request to the same page (or the EDD processing handler) with the following parameters: 'edd_action' set to 'reset_password', 'edd_user_login' set to a valid username/email, 'edd_password_nonce' set to the extracted nonce, and 'edd_redirect' set to the target external URL (e.g., 'https://evil.com'). 4. Submit the request. If successful, the server will respond with a 302 Found status, and the 'Location' header will contain the attacker-supplied URL, demonstrating the unvalidated redirect.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.