我正在为涉及SQL注入的安全类做一些功课。我发现我可以比典型的' OR '1'=1
示例做更短的SQL注入。相反,我可以做'='
。键入此内容是在典型登录框的密码字段中提供如下的SQL查询:
SELECT * FROM Users WHERE username='user' AND password=''='';
事实证明password=''=''
评估为1
,允许SQL注入工作。
在做了一些测试之后,我看到如果我测试一个字符串是否等于0,它会返回1:
SELECT 0='a';
因此,在我的示例中,password=''
将评估为0,而0=''
最终将评估为1。
我的测试向我显示了 这是怎么发生的,但我想知道为什么这种情况发生(即为什么0='a'
是真的?。
答案 0 :(得分:4)
Mysql看到比较并将字符串转换为整数,但这导致一个无效的整数,因此它将其转换为0. 0 = 0所以它的真(1)
答案 1 :(得分:4)
如Type Conversion in Expression Evaluation所述,字符串和整数之间的比较将以数字方式执行:
- 在所有其他情况下,将参数作为浮点(实数)进行比较。
因此,操作数将转换为浮点数,然后进行比较。
将字符串转换为float将考虑遇到第一个非数字字符的每个数字字符(以及第一个句点或取幂字符)。因此,'hello'
或'a'
将被截断为''
(从而转为零),而'123.45e6foo789'
将截断为'123.45e6'
(从而转换为123,450,000)。
因此可以看出0='a'
是如何成立的:它被比作0=0
。
password=''=''
为真(假设 password
是非空字符串,或非零数字),因为第一次比较结果为零( false),强制第二次比较以数字方式执行(因此将''
转换为零,以便与第一次比较的零结果进行比较)。
答案 2 :(得分:0)
对于SELECT 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';
所有列都是true,但适用于:
select 0='1a';
将为false,因为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'