我最近正在向我的朋友解释参数化及其优点,他问在安全性方面如何优于mysqli_escape_string
。具体地说,您是否能想到尽管输入字符串被转义(使用mysqli_escape_字符串),SQL注入仍然会成功的例子?
更新:
我为我最初的问题不够清楚而道歉。这里要问的一般问题是,尽管转义了输入字符串,SQL注入是否可能?
最佳答案
更新的答案
这个问题被编辑(在我的答案发布后)到特定的targetmysqli_escape_string
,它是mysql_real_escape_string
的别名,因此考虑了连接编码。这使得原来的答案不再适用,但我为了完整性而留下了它。
简而言之,新的答案是:mysqli_escape_string
与参数化查询一样具有良好的安全性,前提是您不要自找麻烦。
具体来说,PHP上的巨大警告中强调了您不应该做的事情:
字符集必须在服务器级别设置,或者使用
使其影响mysqli_set_charset()
。
如果不注意此警告(即,如果使用直接mysqli_real_escape_string()
查询更改字符集),并将字符集从单字节编码更改为“方便”(从攻击者的角度)的多字节编码,则实际上您将模拟dumbSET NAMES
所做的操作:尝试转义字符而不知道哪个编码输入已输入。
这种情况使您可能容易受到SQL注入的攻击,如下面的原始答案所述。
重要提示:我记得在某个地方读到过,最近的MySql版本在它们的端部(在客户端库中?)插入了这个漏洞,这意味着即使使用mysql_escape_string
切换到易受攻击的多字节编码,也可能是完全安全的。但请不要相信我的话。
原始答案
与SET NAMES
相反,baremysql_real_escape_string
不考虑doc page。这意味着它假设输入是单字节编码,而实际上它可以合法地是多字节编码。
一些多字节编码具有对应于单个字符的字节序列,其中一个字节是单引号(mysql_escape_string
)的ASCII值;如果输入这样的字符串,0x27
将很高兴地“转义引号”,这意味着用mysql_escape_string
0x27
替换0x5c
。根据编码规则,这可能导致将多字节字符变异为另一个包含0x27
的字符,并将“剩余的”0x5c
作为独立的单引号留在输入中。喂,您已经在SQL中注入了一个未转义的引号。
有关详细信息,请参见connection encoding。
关于php - mysql_escape_string漏洞,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13026469/