2

我在 cookie 和数据库中都存储了一个 md5 哈希。我有一个函数,validate_cookie()它读取此 cookie 并查询数据库以查找与此哈希关联的用户。

validate_cookie()调用另一个函数get_user_data()来进行实际查询。get_user_data()被其他一些函数和脚本调用,所以它发送的查询非常笼统。这是功能:

function get_user_data($info,$password=Null,$source=Null)
{
  if(!$source)
    {
      $query = "SELECT * FROM `users` WHERE `id` = '".mysql_real_escape_string($info)."' OR `email` = '".mysql_real_escape_string($info)."' OR `cookie`='".mysql_real_escape_string($info)."'"; //Check to see if $info matches any column
    }
  else { $query = "SELECT * FROM `users` WHERE `".mysql_real_escape_string($source)."_token` ='".mysql_real_escape_string($info)."'";} //we got a social token
  $result = mysql_query($query);

  if($result)
    {
      $row = mysql_fetch_array($result);
      if($password)
    {
      if(crypt($password, $row['password']) == $row['password']) //password matching
        {
          return $row;
        } else {return "Password does not match!";}
    }
      else { return $row; }
    } 
  else { return "Could not get result from database!";}
}

在这种情况下,重要的查询位于if(!source){}块内。随着validate_cookie()调用方式,get_user_data()这个查询变成了(我已经测试过它确实变成了这个):

SELECT * FROM `users` WHERE `id` = '8sd8sdvsasdliwerhnbzo823' OR `email`='8sd8sdvsasdliwerhnbzo823' OR `cookie`='8sd8sdvsasdliwerhnbzo823'

因为id是一个 int 字段,并且其中的所有内容email都经过验证,所以应该从此查询中选择的唯一行是具有匹配cookie字段的行。

NULL但是,无论是从 PHP 脚本调用此查询还是从 PHPMyAdmin 手动调用,这将始终选择目标行和另一行:仅在其cookie字段中的测试用例。稍微改变哈希(这样它根本不应该匹配任何东西)仍然选择相同的测试用例。

我的查询是否以我无法理解的方式格式错误?是否有一些神秘的用途OR可以NULL匹配字段?任何帮助,将不胜感激。

PS 在我被告知我应该真正使用之前mysqli,是的,我知道这一点。mysql是老板的命令。

4

2 回答 2

2

http://sqlfiddle.com/#!2/0b0832/10/0

它将您的哈希转换为整数。您的测试 ID 是 3。您的哈希以 3 开头。它使它们相等。

select cast('3b38f280e0203d7998a0d0898095ed56' as unsigned) as x

产量 3

像这样修复它:

SELECT id, email, password, cookie,

case when `email`  = '3b38f280e0203d7998a0d0898095ed56' then 'email'
     when `id`     = '3b38f280e0203d7998a0d0898095ed56' then 'id'
     when `cookie` = '3b38f280e0203d7998a0d0898095ed56' then 'cookie'
     else 'else' end as wtf
FROM `users`
WHERE  
    cast(`id` as char) = '3b38f280e0203d7998a0d0898095ed56' or
    `email`  = '3b38f280e0203d7998a0d0898095ed56' or
    `cookie` = '3b38f280e0203d7998a0d0898095ed56' 

如果您传入 ID = 3,这仍然有效

于 2013-09-05T21:16:19.667 回答
1

当且当您确定您的 sql 语句演变为以下内容时:

select a,b,[c ...] from mytable where a='something' or b='something' [or ...]

与 a,b [...] 不为 NULL

你只应该得到一行“a”或“b”不为空并且蜂鸣“某事”。如果没有,您的数据库/系统/驱动程序或其他问题

有时“其他人都错了”
这么说,但那是我的经验(在我的情况下,php_db2 我有时没有结果)。

特别是 - 再一次 - 如果您确定您的语句在运行时如何演变,如果“本机”工具,这里 mysql admin 给出相同的 - 错误 - 结果,有问题,不在您的范围内

如果(看起来)您的数据库/驱动程序/安装中存在错误,您可以尝试使用类似的工作方法

select from ... where (a='som' and a is not null) or (b='som' and b is not null...) and so on 

考虑用“TODO:等待正确的数据库安装”左右标记它

顺便提一句:

于 2013-09-05T20:20:52.240 回答