最近我在向我的 friend 解释参数化及其优势,他问我在安全性方面它比 mysqli_escape_string
有什么好处。具体来说,您能想到尽管输入字符串被转义(使用 mysqli_escape_string)仍会成功的任何 SQL 注入(inject)示例吗?
更新:
对于我最初的问题不够清楚,我深表歉意。这里提出的一般问题是,尽管转义了输入字符串,是否可能进行 SQL 注入(inject)?
最佳答案
更新的答案
问题经过编辑(在我的回答发布后)专门针对 mysqli_escape_string
,它是 mysql_real_escape_string
的别名,因此考虑了连接编码。这使得原始答案不再适用,但为了完整起见,我将其保留。
简而言之,新答案:mysqli_escape_string
在安全方面与参数化查询一样好,前提是您不要搬起石头砸自己的脚。
具体来说,PHP doc page 上的巨大警告中突出显示了您不能做的事情。 :
The character set must be set either at the server level, or with the API function
mysqli_set_charset()
for it to affectmysqli_real_escape_string()
.
如果您不注意此警告(即,如果您使用直接的 SET NAMES
查询更改字符集)并且您将字符集从单个 -字节编码转换为“方便的”(从攻击者的角度来看)多字节编码,您实际上模拟了愚蠢的 mysql_escape_string
所做的事情:在不知道输入采用哪种编码的情况下尝试转义字符。
如以下原始答案所述,这种情况使您可能容易受到 SQL 注入(inject)攻击。
重要说明:我记得在某处读到最近的 MySql 版本已经在其末端(在客户端库中)堵上了这个漏洞,这意味着您可能是完美的即使使用 SET NAMES
切换到易受攻击的多字节编码也是安全的。但请不要相信我的话。
原始答案
与 mysql_real_escape_string
相比,裸 mysql_escape_string
不考虑 connection encoding .这意味着它假定输入采用单字节编码,而实际上它可以合法地采用多字节编码。
一些多字节编码具有对应于单个字符的字节序列,其中一个字节是单引号的 ASCII 值 (0x27
);如果输入这样的字符串,mysql_escape_string
将愉快地“转义引号”,这意味着将 0x27
替换为 0x5c
0x27
.根据编码规则,这可能导致将多字节字符突变为包含 0x5c
的另一个字符,并将“剩余的”0x27
作为独立的单个字符在输入中引用。瞧,您已将未转义的引号注入(inject)到 SQL 中。
有关详细信息,请参阅 this blog post .
关于php - mysql_escape_string 漏洞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13026469/