MySQL的逻辑运算符(and_or_xor)的工作机制

起因

  在做基于时间盲注测试的时候,发现sleep的时间和预想的时间不同,为了解释此现象,于是乎就开始探究and、or、xor的工作机制。

  如果你以前以为 and sleep(5) 、or sleep(5)就是延时5秒,那恭喜你,这篇文章会让你学到一些东西。

数据库中的内容

1
2
3
4
5
6
7
--MySQL.user 表

host user password
localhost root mysql5('root')
127.0.0.1 root mysql5('root')
192.168.0.100 root mysql5('root')
localhost aaa mysql5('root')

测试语句及结果

测试语句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
2
-- 情况1:
id and if(1=1,sleep(5),0)

  如果这里你填写的ID是在数据库中不存在的ID,则这个payload不会延时,那么你将错过一个基于时间的盲注注入点。

1
2
-- 情况2:
id or if(1=1,sleep(5),0)

  如果这里有100个id,而你只写了1个id,那么你将进行99次sleep(5),同志,你想想你等待的会不会花儿都谢了?

1
2
-- 情况3:
keyword%' and if(1=1,sleep(5),0) or '%a%'='%a

  这种情况会延时0秒,MySQL会从简单的一方先开始查询,显然’%a%’=’%a%’已经占了全集,那么or左边的sleep(5)

  and 左右一旦出现明显的false则不会执行另一次,or 左右一旦出现明显true则不会执行另一侧,这是我在写第三种情况的时候发现的

1
2
-- 情况4:
keyword%' or if(1=1,sleep(5),0) or '%a%'='%a

  此情况延时也为0秒,因为最右侧出现了明显的true

1
2
-- 情况5:
keyword%' and if(1=1,sleep(5),0) or '%a%'='%a

  此情况延时也为0秒,因为最右侧出现了明显的true

总结

  1.在不需要闭合的注入场景中尽量使用id and if(1=1,sleep(5),0) 并且注意id要填写为数据库中存在的id

  2.在需要闭合的注入场景中,keyword最好填写能查询数据,并且查询的条目不多的keyword,两个连接符都用and来进行连接。