10

我正在为涉及 SQL 注入的安全课程做一些功课。我发现我可以执行比典型' OR '1'=1示例更短的 SQL 注入。相反,我可以做到'='。在典型登录框的密码字段中键入 this 会给出如下 SQL 查询:

SELECT * FROM Users WHERE username='user' AND password=''='';

事实证明,password=''=''计算结果为1,允许 SQL 注入工作。

在做了一些测试之后,我看到如果我测试一个字符串是否等于 0,它会返回 1:

SELECT 0='a';

因此,在我的示例中,password=''将评估为 0,0=''最终评估为 1。

我的测试向我展示了这是如何发生的,但我想知道为什么会发生这种情况(即为什么是0='a'真的?。

4

3 回答 3

6

表达式评估中的类型转换中所述,字符串和整数之间的比较将以数字方式执行:

  • 在所有其他情况下,参数作为浮点(实)数进行比较。

因此,操作数被转换为浮点数,然后进行比较。

将字符串转换为浮点数将考虑遇到的每个数字字符(以及第一个句点或指数字符),直到第一个非数字字符。因此'hello'or'a'将被截断为''(从而强制为零),而'123.45e6foo789'将被截断为'123.45e6'(从而强制为 123,450,000)。

因此,人们可以看到它是如何0='a'为真的:它被比较为0=0

password=''=''是真的(前提 password是非空字符串或非零数字),因为第一次比较结果为零(假),这迫使第二次比较以数字方式执行(因此转换''为零以进行比较第一次比较的零结果)。

于 2013-10-06T23:03:15.487 回答
4

Mysql 看到比较并将字符串转换为整数,但这会导致整数无效,因此将其强制转换为 0。 0=0 所以它是 true(1)

于 2013-10-06T22:37:01.917 回答
0

对于选择 0='a', 0='';

1. type of 0 is int 
2. type of 'a' is char  then CAST( 'a' AS UNSIGNED ) or CAST( '' AS UNSIGNED ) will be 0

将 char 转换为 int 然后 0=0 在您的情况 1 中评估为 true。在:

select 'A'='a', 0=0, '0'='a',0='a1';

所有列都为真,但对于:

select 0='1a';

将是错误的,因为 CAST('1a' AS UNSIGNED) 为 1。

mysql> SELECT 'asadsadsa' = 'a', 0 = 'az', cast( 'az' AS unsigned ) , 'asadsadsa' = 'a' = 'az', 0 =0;
      +-------------------+----------+--------------------------+--------------------------+------+
      | 'asadsadsa' = 'a' | 0 = 'az' | cast( 'az' AS unsigned ) | 'asadsadsa' = 'a' = 'az' | 0 =0 |
      +-------------------+----------+--------------------------+--------------------------+------+
      |                 0 |        1 |                        0 |                        1 |    1 |
      +-------------------+----------+--------------------------+--------------------------+------+
      1 row in set, 3 warnings (0.00 sec)

      Warning (Code 1292): Truncated incorrect DOUBLE value: 'az'
      Warning (Code 1292): Truncated incorrect INTEGER value: 'az'
      Warning (Code 1292): Truncated incorrect DOUBLE value: 'az'
于 2013-10-06T22:42:18.720 回答