在mysqli_real_escape_string()的PHP文档中,写的是
注意 安全性:默认字符集
字符集必须在服务器级别设置,或者使用 API函数mysqli_set_charset()让它影响 mysqli_real_escape_string()。
在关于字符集的进一步链接中,提到了
应该理解和定义字符集,因为它具有 影响每一个行动,并包括安全隐患。
Suource Character sets
为了安全起见,为什么必须设置字符集以及它包含哪些安全隐患? 任何人都可以解释这些背后的概念吗?
提前致谢
答案 0 :(得分:4)
如何解析SQL查询取决于连接字符集。如果您执行了此查询:
$value = chr(0xE0) . chr(0x5C);
mysql_query("SELECT '$value'");
然后如果连接字符集是Latin-1,MySQL会看到无效:
SELECT 'à\'
如果字符集是Shift-JIS,则字节序列0xE0,0x5C将被解释为双字节字符:
SELECT '濬'
为安全性添加字符串文字转义:
$value = mysql_real_escape_string($value);
mysql_query("SELECT '$value'");
现在,如果您使用mysql_set_charset
正确地将连接字符集设置为Shift-JIS,MySQL仍会看到:
SELECT '濬'
但是如果你没有设置连接字符集,并且MySQL的默认字符集是Shift-JIS但是PHP的默认字符集是ASCII,那么PHP不知道尾随的0x5C字符是双字节序列的一部分并且逃避它,认为它正在生成有效的输出:
SELECT 'à\\'
虽然MySQL使用Shift-JIS将其读取为:
SELECT '濬\'
使用反斜杠转义尾随'
,这会使字符串文字保持打开状态。查询中的下一个'
字符将结束字符串,留下原始SQL内容中的后续内容。如果你可以在那里注入,那么查询就容易受到攻击。
此问题仅适用于少数东亚编码,例如Shift-JIS,其中多字节序列可以包含字节,这些字节本身就是反斜杠等有效的ASCII字符。如果不匹配的编码都将低字节视为始终为ASCII(严格的ASCII超集,如拉丁-1与UTF-8的更常见的不匹配),则不会出现这种混淆。
幸运的是,默认使用这些编码的服务器并不常见,因此在实践中这是一个很少可利用的问题。但如果您 使用mysql_real_escape_string
,那么您应该正确行事。 (最好通过使用参数化查询来完全避免它。)
答案 1 :(得分:1)
如果您想secure your applications against SQL injection,则应该使用预备语句而不是转发输入。 (不要让MySQLi或PDO模拟准备;如果可以,请使用真实的预处理语句!)
只有在您不能使用预准备语句的情况下才能考虑转义(动态生成的查询,LIMIT
)。在这些特定情况下,请确保您不是making mysqli_real_escape_string()
bypassable because of misconfigured character sets。 (ircmaxell的这个链接的StackOverflow答案比我更好地解释了这个问题。)
WordPress最近出现了一个问题,即多字节字符可以绕过他们的SQL转义策略the security team patched it under the guise of Emoji support。
如果您正在使用mysql_real_escape_string()
或mysqli_real_escape_string()
,那么您正在玩火。小心你不要被烧伤。