这三个 SQL 查询之间有什么区别?



这三个查询在安全性和良好的编码语法方面有什么区别?

查询1

$sql = "SELECT user_id,
               user_email,
               user_pass
          FROM user_tb 
         WHERE user_email ="".$e."" 
           AND user_pass = md5("".$p."") ";
查询2

$sql = "SELECT user_id,
               user_email,
               user_pass
          FROM user_tb 
         WHERE user_email = '$e' 
           AND user_pass = '$p' ";
查询

3

$sql = "SELECT user_id,
               user_email,
               user_pass
          FROM user_tb 
         WHERE user_email = $e 
           AND user_pass = $p ";

这三个都没有有效的安全性,并且容易受到任何sql注入的影响。你可以在变量周围使用mysql_real_escape_string(),或者使用准备好的语句来保证安全。

话虽如此,在$e和$p变量周围加上引号只会确保在这些值为空的情况下不会出现sql错误。

第一个对变量($e和$p)执行字符串连接,另外使用MD5函数获取密码的哈希值,以便与USER_TB.user_pass列值进行比较。如果值没有作为散列存储,MD5就没有任何用处——因为没有任何东西可以匹配。

第二个示例缺少MD5函数的使用,但是在单引号中适当地将变量括起来,以便与列值进行比较时将其视为字符串字面值。

第三个查询缺少用于正确处理SQL字符串的单引号,并且使用MD5函数。

总结

这三个都容易受到SQL注入攻击。如果不使用PDO, sprintf是使用预处理语句的解决方案:

$query = sprintf("SELECT t.user_id,
                         t.user_email,
                         t.user_pass
                    FROM USER_TB t
                   WHERE t.user_email = '%s' 
                     AND t.user_pass = '%s'",
                  mysql_real_escape_string($e),
                  mysql_real_escape_string($p));
$result = mysql_query($query);

在我的书中它们都失败了,除非$e$p都已经在屏幕外进行了消毒。如果是这样的话,那么第2条就胜出了。MD5是一个弱散列。与MySQL相比,PHP可以使用hash_hmac() sha512或其他库(每个人都会有这样的说法)执行更强的哈希。如果你不顾一切地使用md5(),我可以想象php在这里会比MySQL执行得更快,但这不是安全问题。除此之外,#1和#2是并列的。

#3的问题是,由于某种原因,$e或$p可能为空。你的查询将是where user_email= AND user_pass,你会得到一个讨厌的MySQL语法错误。除了他们可能得到的其他卫生条件外,他们还需要用引号括起来,否则卫生条件对你没有任何好处。

编辑:正如OMG Ponies指出的那样,您需要与md5()(或任何散列)检查保持一致性。这是我的假设,密码哈希存储和查询#2和#3上面,$user_pass是由php哈希在查询中使用之前。

我也喜欢"查询2"。它的安全性为0,这很容易受到sqlinject的攻击。

您应该对$e和$p字符串进行消毒,并确保它没有像+/*——' "等坏字符

最新更新