SQL 查询说明中的 SLEEP(x) 角色

SLEEP(x) role in SQL query clarification

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

SELECT * FROM users WHERE name = ''

returns 0 应有的记录

SELECT * FROM users WHERE name = 'janet'

returns 1 应该记录

SELECT * FROM users WHERE name = ''-SLEEP(3)

returnsEVERY条记录在table,为什么??

SLEEP(3) returns 0

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

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

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

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

documentation for the sleep function 状态:

Sleeps (pauses) for the number of seconds given by the duration argument, then returns 0. If SLEEP() is interrupted, it returns 1. The duration may have a fractional part.

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

WHERE Name = 0;

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

The following rules describe how conversion occurs for comparison operations:

  • If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
  • If both arguments in a comparison operation are strings, they are compared as strings.
  • If both arguments are integers, they are compared as integers.
  • Hexadecimal values are treated as binary strings if not compared to a number.
  • If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
  • If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
  • In all other cases, the arguments are compared as floating-point (real) numbers.

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

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

哪个会给你0.00000。因此,发生转换后的最终 where 子句是:

WHERE 0 = 0;

因此返回所有行。

在MySQL中,SLEEP()是returns0.

的函数

文档说它 returns 1 当它被中断时,但它没有解释如何实现这种行为。我认为在此讨论中始终假设它 returns 0 是安全的。

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

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

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

The following rules describe how conversion occurs for comparison operations:

  • If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
  • If both arguments in a comparison operation are strings, they are compared as strings.
  • If both arguments are integers, they are compared as integers.
  • Hexadecimal values are treated as binary strings if not compared to a number.
  • If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
  • A single-row subquery from a table or tables is not considered a constant. For example, if a subquery returns an integer to be compared to a DATETIME value, the comparison is done as two integers. The integer is not converted to a temporal value. To compare the operands as DATETIME values, use CAST() to explicitly convert the subquery value to DATETIME.
  • If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
  • In all other cases, the arguments are compared as floating-point (real) numbers.

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

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

这是对您的查询明显怪异行为的解释。