起因
在做基于时间盲注测试的时候,发现sleep的时间和预想的时间不同,为了解释此现象,于是乎就开始探究and、or、xor的工作机制。
如果你以前以为 and sleep(5) 、or sleep(5)就是延时5秒,那恭喜你,这篇文章会让你学到一些东西。
数据库中的内容
1 | --MySQL.user 表 |
测试语句及结果
测试语句1
1 | mysql> select user,password from user where user='root' and sleep(5); |
疑问1:为什么这里是延时了15秒?
测试语句2
1 | mysql> select user,password from user where user='aaa' or sleep(5); |
疑问2:为什么这里也是延时了15秒?
测试语句3
1 | mysql> select user,password from user where user='root' and host='localhost' or sleep(5); |
疑问3:为什么又是15秒?
测试语句4
1 | mysql> select user,password from user where user='root' or sleep(5) and host='localhost'; |
终于是5秒了,我仿佛又看到了春天。
测试语句5
1 | mysql> select user,password from user where host='localhost' or sleep(5) and user='root'; |
疑问4:纳尼?怎么又是10秒了?这究竟发生了什么?
测试语句6
1 | mysql> select user,password from user where host='localhost' or user='root' or sleep(5); |
疑问5:纳尼?前面的延时时间比预期的时间长就算了,这个怎么还不延迟了呢?
测试语句7
1 | mysql> select user,password from user where host='localhost' or false and user='root' and sleep(5); |
疑问6:0秒?楼主你的MySQL是假的吧。
让我来一一回答这六个疑问。
and 、or的工作机制
这里要先说明一个问题:sleep(5)<=>false
第一个问题
1 | mysql> select user,password from user where user='root' and sleep(5); |
以上语句执行时间为什么是15秒?
这个问题涉及到了MySQL中and的工作机制,比如where A and B。MySQL会先进行查询满足条件A的结果集:
1 | select * from user where A; -- 假设返回结果集1 |
然后从结果集1中查询满足条件B的:
1 | select * from 结果集1 where B; |
由于满足user=’root’的结果集中包含3个数据,所以sleep(5)被执行了3次,因此延时15秒。
第二个问题
1 | mysql> select user,password from user where user='aaa' or sleep(5); |
这个语句为什么也是延时15秒?
这个问题涉及到了MySQL or的工作机制,比如where A or B,MySQL会先查询出非A的结果集1:
1 | select * from user where not A; |
然后在结果集1中查询出非B的结果集2:
1 | select * from 结果集1 where not B; |
第三步是从user表中查询非结果集2的结果,也就是最终结果:
1 | select * from user where not 结果集1; |
我们构造的环境中,user!=’aaa’的有3条记录,所以sleep(5)被执行了3次,因此延时15秒
第三个问题
1 | mysql> select user,password from user where user='root' and host='localhost' or sleep(5); |
这条语句为什么延时15秒?
这条语句先查询出满足user=’root’的结果集1[3条],然后再从结果集1中查询出满足host=’localhost’的结果集2[1条],接着从非结果集2[3条]中查询非sleep(5)得到结果集3,最后查询非结果集3的即可获得最终数据,此过程中sleep(5)被执行了3次,因此延时15秒
第四个问题
1 | mysql> select user,password from user where host='localhost' or sleep(5) and user='root'; |
为什么会延时10秒?
这条语句先查询出host=’localhost’的结果集1,然后再对非结果集1进行(sleep(5) and user=’root’)的筛选得出结果集2,结果集1和结果集2的并集就是最终结果集。
而从非结果集1中进行where sleep(5) and user=’root’的查询又分为以下两步:1.从非结果集1中查询满足sleep(5) 的结果集2_1 然后从结果集2_1中查询满足user=’root’的结果集得到结果集2
另外从该语句的执行结果我们可以看出的是and的优先级要高于or。如果两者优先级相同的话,结果应该是只有一条数据:localhost root的这条。
1 | mysql> select user,password from user where host='localhost' or user='xxxx' and sleep(5); |
原因是非结果集1中满足user=’xxxx’的结果集2_1为空,所以sleep(5)未执行。
第五个问题
1 | mysql> select user,password from user where host='localhost' or user='root' or sleep(5); |
为什么执行结果是0秒呢?
因为host=’localhost’ or user=’root’已经是全集了,非全集则为空集,所以sleep(5)没有被执行。
第六个问题
1 | mysql> select user,password from user where host='localhost' or false and user='root' and sleep(5); |
为什么执行结果是0秒呢?
因为false and user=’root’的结果集已经是空集,所以sleep(5)并没有被执行。
xor的工作机制
对时间盲注的影响
1 | -- 情况1: |
如果这里你填写的ID是在数据库中不存在的ID,则这个payload不会延时,那么你将错过一个基于时间的盲注注入点。
1 | -- 情况2: |
如果这里有100个id,而你只写了1个id,那么你将进行99次sleep(5),同志,你想想你等待的会不会花儿都谢了?
1 | -- 情况3: |
这种情况会延时0秒,MySQL会从简单的一方先开始查询,显然’%a%’=’%a%’已经占了全集,那么or左边的sleep(5)
and 左右一旦出现明显的false则不会执行另一次,or 左右一旦出现明显true则不会执行另一侧,这是我在写第三种情况的时候发现的
1 | -- 情况4: |
此情况延时也为0秒,因为最右侧出现了明显的true
1 | -- 情况5: |
此情况延时也为0秒,因为最右侧出现了明显的true
总结
1.在不需要闭合的注入场景中尽量使用id and if(1=1,sleep(5),0) 并且注意id要填写为数据库中存在的id
2.在需要闭合的注入场景中,keyword最好填写能查询数据,并且查询的条目不多的keyword,两个连接符都用and来进行连接。