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()?