【问题标题】:MySQL `WHERE ` is giving unexpeted results for matching 0MySQL `WHERE` 给出了匹配 0 的意外结果
【发布时间】:2014-04-19 11:25:44
【问题描述】:

我有user_info表描述如下

Field          Type         null Type        Extra
usr_id     int(11)           NO  PRI           auto_increment
f_name     varchar(50)       NO         
l_name     varchar(50)       YES            
user_name  Varchar(45)       NO         
password   varchar(128)      NO         
email      varchar(50)       NO         
type       enum('a','s','c') NO 

表格内的数据

0   admin   admin   admin   d033e22ae348aeb5660fc2140aec35850c4da997    admin@oww.com   a
1   staff   Staffer staff   d033e22ae348aeb5660fc2140aec35850c4da997    staff@oww.com   s
2   staff2  stafer  staff2  d033e22ae348aeb5660fc2140aec35850c4da997    staff2@oww.com  s
10  Shanoop Pattanath   shan123456  5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8    shan@shan.com   s

SQL 查询

SELECT 
    *
FROM
    (`user_info`)
WHERE
    `user_name` = 0  -- wrong input 
        AND `password` = 0 -- wrong input
ORDER BY `usr_id`;

此查询的结果

0   admin   admin   admin   d033e22ae348aeb5660fc2140aec35850c4da997    admin@oww.com   a
1   staff   Staffer staff   d033e22ae348aeb5660fc2140aec35850c4da997    staff@oww.com   s
2   staff2  stafer  staff2  d033e22ae348aeb5660fc2140aec35850c4da997    staff2@oww.com  s

这个查询怎么会匹配所有数据?这个查询不应该给出任何结果,不是吗?我在这里做错了什么?详细的答案非常感谢MySQL ver : 5.5.35-0ubuntu0.13.10.2 (Ubuntu)SQL FIddle

所有用户名、密码和电子邮件都是虚构的

更新 我知道0 必须在引号内。我通过这样做解决了这个问题。但是 MySQL 怎么会给出这个有线输出。 ?

【问题讨论】:

  • 喜欢你的问题....非常好和奇怪的查询输出
  • 在 0 ('0') 周围添加引号可以解决问题,您应该这样做。
  • @user1153551 这几乎在我的网站中造成了巨大的安全问题。我找到SQL注入的新方法了吗?
  • @FDL 我知道,但为什么会给出这个结果?
  • 因为您将整数与字符串值进行比较。很可能当 SQL 将字符串转换为整数进行比较时,它会转换为 0。然后匹配。

标签: mysql sql select where


【解决方案1】:

执行的比较似乎是intint

MySQL 正在将 user_namepassword 中的文本转换为 int 以进行比较。 MySQL 文档here 表明varchar 在这种操作中会被转换为int

如果您查看此SQL Fiddle,您会发现在user_namepassword 字段上使用CONVERT 将它们设为int 将输出0,从而使您的比较成立。

如果您要比较两个 varchar 值,请确保用单引号括住您的条件:

user_name = '0'
AND password = '0'

顺便说一句,好问题!

【讨论】:

  • 哇,我不知道这个,非常感谢你提供的知识。 select '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8' = 0; 给出 0 这就是跳过最后一行的原因。有什么方法可以避免这种类型转换?我认为这可能会导致sql注入。当我们对 Igniter 输入类进行编码时。
【解决方案2】:

检查这个fiddle

问题是user_namevarchar0INT
您无法比较 INTString

通过练习,你应该把它放在像这样的 qoutes 中:

`user_name` = '0'  -- wrong input 
 AND `password` = '0' -- wrong input

但是,如果您想确保比较的数据始终是字符串。 您可以尝试以下方法:

 WHERE `user_name` = CAST(0 AS CHAR);

如果你愿意

SELECT *
FROM supportContacts
WHERE type = 1;

它不会返回任何东西。

为什么?这是因为它将您的列转换为整数。任何没有有效整数的字段都将等于 0。您应确保仅将字符串字段与字符串值进行比较。

【讨论】:

  • 是的,感谢您的回答,这个问题也让我感到困惑。现在好了
  • @majimboo 当我们尝试匹配错误的数据类型时,它必须给出 SQL 错误。相反,这会给出结果。有趣的是它没有给出最后一行,你注意到了吗?
  • @Shanoop 是的,这很奇怪。即使在小提琴上也可以复制。但这可能是因为给出的 int 是0。会进一步研究。
  • 这是 MySQL burg ??我在 PostgreSQL 上尝试它的返回类型转换错误。
  • @user1153551:MySQL 更喜欢返回“某些结果可能是您的意思”,而不是抛出错误并告诉您正在将苹果与橙子进行比较。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 2017-07-11
  • 2013-12-20
  • 1970-01-01
  • 2012-01-23
相关资源
最近更新 更多