SLEEP(x)在SQL查询澄清中的作用

时间:2015-02-16 15:38:54

标签: mysql sql sleep

我不明白为什么会这样。 有人可以解释一下吗?

SELECT * FROM users WHERE name = ''

应该

返回 0 记录
SELECT * FROM users WHERE name = 'janet'

应该

返回 1 记录
SELECT * FROM users WHERE name = ''-SLEEP(3)

在表格中返回每条记录,为什么??

SLEEP(3) returns 0

使用name = ''-0产生相同的结果(返回每条记录)

这不适合实际使用,因为我正在测试基于时间的SQL注入

3 个答案:

答案 0 :(得分:2)

MySQL正在截断varchar值,并在Where子句中评估0 = 0。执行查询,然后执行show warnings;以查看varchar值是否被截断。

MySQL隐式转换:http://dev.mysql.com/doc/refman/5.5/en/type-conversion.html

答案 1 :(得分:2)

documentation for the sleep function州:

  

暂停(暂停)持续时间参数给出的秒数,然后返回0.如果SLEEP()中断,则返回1.持续时间可能有小数部分。

所以它返回一个整数,所以你实际拥有的是'' - 0,这里''被隐式转换为一个整数,所以这两种类型是可比的,所以你有0 - 0等于0,所以你的where子句实际上是:

WHERE Name = 0;

由于您要将字符串与整数进行比较,因此必须进行类型转换。以下是MySQL Docs

  

以下规则描述了比较操作的转换方式:

     
      
  • 如果一个或两个参数为NULL,则比较结果为NULL,但NULL-safe< =>除外。平等比较运算符。对于NULL< => NULL,结果为true。无需转换。
  •   
  • 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。
  •   
  • 如果两个参数都是整数,则将它们作为整数进行比较。
  •   
  • 如果不与数字进行比较,十六进制值将被视为二进制字符串。
  •   
  • 如果其中一个参数是TIMESTAMP或DATETIME列而另一个参数是常量,则在执行比较之前将常量转换为时间戳。这样做是为了更友好的ODBC。请注意,这不是针对IN()的参数!为安全起见,在进行比较时始终使用完整的日期时间,日期或时间字符串。例如,要在将BETWEEN与日期或时间值一起使用时获得最佳结果,请使用CAST()将值显式转换为所需的数据类型。
  •   
  • 如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较,如果另一个参数是浮点值,则将参数作为浮点值进行比较。
  •   
  • 在所有其他情况下,将参数作为浮点(实数)进行比较。
  •   

由于您有一个字符串参数,而一个是整数,因此它是最后一个子句。将字符串(不是数字)转换为浮点数会导致错误0,您可以使用以下简单的方法进行测试:

SELECT  CAST('A String' AS DECIMAL(10,5));

哪个会给你0.00000。所以转换后的最终where子句是:

WHERE 0 = 0;

所以返回所有行。

答案 2 :(得分:0)

在MySQL中,SLEEP()是一个返回0的函数。

文档说它在被中断时返回1,但它没有解释如何实现这种行为。我认为可以安全地假设它总是返回0进行讨论。

WHERE表达式name = '' - SLEEP(3)的计算方法如下:

  • MySQL调用SLEEP(3)函数;三秒钟后,它返回整数值0;
  • '' - 0(空字符串减零)被计算为数值表达式(没有为字符串定义减法运算符);空字符串转换为数字0,表达式的值为数字0(零);
  • WHERE子句变为name = 0,其中0是一个数字。

关于Type Conversion in Expression Evaluation的文档页面包含用于在比较不同类型的值时转换它们的规则列表:

  

以下规则描述了比较操作的转换方式:

     
      
  • 如果一个或两个参数为NULL,则比较结果为NULL,但NULL-safe< =>除外。平等比较运算符。对于NULL< => NULL,结果为true。无需转换。
  •   
  • 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。
  •   
  • 如果两个参数都是整数,则将它们作为整数进行比较。
  •   
  • 如果不与数字进行比较,十六进制值将被视为二进制字符串。
  •   
  • 如果其中一个参数是TIMESTAMP或DATETIME列而另一个参数是常量,则在执行比较之前将常量转换为时间戳。这样做是为了更友好的ODBC。请注意,这不是针对IN()的参数!为安全起见,在进行比较时始终使用完整的日期时间,日期或时间字符串。例如,要在将BETWEEN与日期或时间值一起使用时获得最佳结果,请使用CAST()将值显式转换为所需的数据类型。
  •   
  • 一个或多个表中的单行子查询不被视为常量。例如,如果子查询返回要与DATETIME值进行比较的整数,则比较将作为两个整数完成。整数不会转换为时间值。要将操作数作为DATETIME值进行比较,请使用CAST()将子查询值显式转换为DATETIME。
  •   
  • 如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较,如果另一个参数是浮点值,则将参数作为浮点值进行比较。
  •   
  • 在所有其他情况下,将参数作为浮点(实数)进行比较。
  •   

从此列表中可以看出,最后一条规则是适用于WHERE子句name = 0的规则。两个操作数都转换为浮点数。

将字符串转换为整数或浮点数将产生0字符串不是数字的表示。

这是对查询显然奇怪的行为的解释。