mysql_real_escape_string() 坏了吗?

Posted

技术标签:

【中文标题】mysql_real_escape_string() 坏了吗?【英文标题】:Is mysql_real_escape_string() broken? 【发布时间】:2011-07-14 10:07:48 【问题描述】:

有些人认为mysql_real_escape_string() 存在一些缺陷,即使正确使用也无法保护您的查询。 带上一些fossilized articles 作为证明。

所以,问题是:mysql[i]_real escape_string() 完全不能接受吗? 或者仍然可以使用这个函数来创建你自己的预处理语句?

请提供验证码。

【问题讨论】:

【参考方案1】:

来自MySQL’s C API function mysql_real_escape_string description:

如果您需要更改连接的字符集,您应该使用mysql_set_character_set() 函数而不是执行SET NAMES(或SET CHARACTER SET)语句。 mysql_set_character_set() 的作用类似于SET NAMES,但也会影响mysql_real_escape_string() 使用的字符集,而SET NAMES 则不会。

所以不要使用SET NAMES/SET CHARACTER SET,而是使用php’s mysql_set_charset 来更改编码,因为它与MySQL 的mysql_set_character_set 对应(参见source code of /ext/mysql/php_mysql.c)。

【讨论】:

好的,那么如果我们使用没有本地字符集设置方法的 mysqli 或 PDO 会发生什么?准备好的语句安全吗? @Charles:MySQLi 确实有对应的函数:mysqli_set_charset。而对于prepared statements,使用preparing a string type时考虑的character_set_client system variable:“MYSQL_TYPE_STRING表示字符输入字符串数据。假定该值位于由character_set_client 系统变量指示的字符集中。” 谢谢!那么,PDO 似乎是唯一缺少的。它有a charset param in the DSN,但它被标记为“当前被忽略..” @Charles,在连接字符串中设置字符集是否有效? real_escape_string 这样可以正常工作吗? @Pacerier,截至我四年前写该评论时,不,它曾经不起作用。 "DSN" == "连接字符串。"从那时起,如链接的手册页中所述,它已开始工作。【参考方案2】:

但是,即使使用遗留代码和旧服务器版本,只有将数据库连接的字符集从像 Latin-1 的单字节字符集更改为允许值 0x5c ( ASCII 单引号)在多字节字符的第二个或更高字节中。

具体来说,UTF-8 不允许这样做,这与 GBK 和 SJIS 等较旧的亚洲编码不同。因此,如果您的应用程序不更改连接字符集,或者仅将其更改为 UTF-8 或像 Latin-n 这样的单字节字符集,那么您就可以免受此攻击。

但最佳做法仍然是运行最新的服务器版本,使用正确的界面来更改字符集,并使用准备好的查询,这样您就不会忘记转义内容。

【讨论】:

【参考方案3】:

在 cmets 中有一个指向 mySQL 5.0.22 (24 May 2006) 中的错误修复的链接,该问题已在此处得到解决。

【讨论】:

以上是关于mysql_real_escape_string() 坏了吗?的主要内容,如果未能解决你的问题,请参考以下文章

mysql_real_escape_string() 坏了吗?

如何在 PDO 中使用/编写 mysql_real_escape_string? [复制]

sqli-labs less37 POST- Bypass MYSQL_real_escape_string (POST型绕过MYSQL_real_escape_string的注入)

使用准备好的语句时是不是需要 mysql_real_escape_string()?

什么是 mysql_real_escape_string() 而addslashes() 没有?

MySQL QUOTE() 与 mysql_real_escape_string()?