为什么mysql_real_escape_string()不应该避免任何SQL注入?

时间:2011-12-19 11:48:34

标签: php mysql security sql-injection

我听过有人说(关于C#/ SQL Server,但也与PHP / MySql有关):不要手动转义字符串 - 改为使用存储过程

好的,我可以接受这个建议,但为什么呢?许多人说(包括在SO上)mysql_real_escape_string()已经足够了,mysql_real_escape_string()很好,mysql_real_escape_string()是第一种保护方式。

为什么呢?是否存在mysql_real_escape_string()失败的情况?至少一个......我不需要很多:)

4 个答案:

答案 0 :(得分:9)

当mysql_real_escape_string 失败

$sql = "SELECT * FROM users WHERE id=" + mysql_real_escape_string($_GET['id']);

如果$_GET['user_id']设置为 1或1 = 1 ,则没有特殊字符且未过滤。

结果:返回所有行。

情况变得更糟。怎么样......如果$_GET['user_id']设置为 1或is_admin = 1 怎么办?

该功能仅用于单引号内时使用。

答案 1 :(得分:1)

仅供参考: mysql_real_escape_string()无法逃脱%_。如果与LIKE, GRANT, or REVOKE结合使用,这些是MySQL中的通配符。

答案 2 :(得分:0)

mysql_real_escape_string() 可能会失败来清理输入。 由于mysql_real_esacpe_string()在清理字符串时会考虑字符集。 有问题。您可以通过发送查询的mysql_query函数更改字符以更改连接的字符集。但是,mysql_real_escape_string()无视您正在使用的集合,并且它会不正确地逃避某些字符。

另一件事是不断手动调用它。即使将它包装在一个函数中也是P.I.T.A.因为它意味着您必须创建自己的某种数据库包装/数据库抽象层,以便能够自动调用mysql_real_escape_string()

这就是为什么我们在PHP中使用PDO可以帮助我们减轻上述所有内容,并且您可以使用参数化的预处理语句 处理重复查询以改变数据的优选方式。

准备语句,绑定输入变量,它将根据正在使用的数据库驱动程序和连接的字符集清除输入。它的代码更少,更安全。

答案 3 :(得分:0)

mysql_real_escape_string()和SQL Injection只有一件事 -

前者与后者没有丝毫关系。

虽然这听起来很自相矛盾,但没有比这更真实了。

这是证明它的两个陈述

  1. 你必须只转义引用的字符串,因为这个函数没有其他帮助。
  2. 实际上,您必须转义要添加到查询中的每个字符串,即使是最安全的字符串。只是因为它可能包含一些特殊字符,从而打破了查询(就像意外,而不是恶意情节)。
  3. 因此,在适用的情况下,无论如何都必须使用此功能,尽管存在任何危险或恐惧。在任何其他情况下,它都没有任何帮助。

    我唯一需要补充的是,预备语句也不能提供全面保护。以下是解释和建议:https://stackoverflow.com/a/8255054/285587