mysql_real_escape_string() 完美吗?
虽然通常用于防范 SQL 注入攻击,但 mysql_real_escape_string() 可以被规避,尽管是在罕见且复杂的情况下。
巧妙的攻击
通过在高度特定的字符集中精心设计的有效负载,mysql_real_escape_string() 可以被利用。详细介绍如下:
-
字符集选择: 服务器的连接字符集必须设置为既支持 ASCII 反斜杠 ('') 又支持最终字节为 ASCII ' 的字符。例如,“gbk”满足此条件。
-
有效负载:选择由字节序列“0xbf27”组成的有效负载。在 'gbk' 中,它是一个无效字符,而在 'latin1' 中,它代表 '¿''。
-
mysql_real_escape_string(): MySQL 对此函数的实现识别连接字符集 (在本例中为“gbk”)并根据其规则应用转义。但是,客户端仍然认为连接正在使用“latin1”。因此,当它使用 'mysql_real_escape_string()' 对字节序列进行转义时,它会插入一个反斜杠。
-
查询: 结果字符串包含一个自由悬挂的 ' 字符:'缞' OR 1=1 /*' in 'gbk'.这是攻击所需的恶意负载。
明显的漏洞
-
PDO 模拟语句:默认情况下,PDO 模拟使用准备好的语句mysql_real_escape_string(),使其容易受到此攻击
-
mysql_real_escape_string() 错误:在 MySQL 4.1.20 和 5.0.22 之前,mysql_real_escape_string() 有一个错误,它将无效的多字节字符视为单个字节,即使客户端是获悉正确的连接编码,允许此攻击
-
PDO 的有限保护措施: PDO 的 DSN 字符集参数(在 PHP ≥ 5.3.6 中引入)并非所有命令都一致支持。这为可利用性留下了空间。
消除阴影
-
安全字符集:利用“utf8”或“utf8mb4”等无懈可击的字符集可以缓解这
-
NO_BACKSLASH_ESCAPES SQL 模式:启用此模式会改变 mysql_real_escape_string() 的功能,防止在易受攻击的编码中创建有效字符。
-
现代 MySQL 版本和准备好的语句: MySQL 版本 5.1(最新), 5.5 及更高版本以及真正的准备好的语句(例如,在 MySQLi 中)不会受到此漏洞的影响。
总之,虽然 mysql_real_escape_string() 通常是有效的,但在特定情况下可能会被绕过。现代版本的 MySQL、适当的字符集选择和真正的准备好的语句可确保完全防御这种复杂的攻击。
以上是`mysql_real_escape_string()` 是否真的能够安全地防止 SQL 注入,或者是否存在微妙的漏洞?的详细内容。更多信息请关注PHP中文网其他相关文章!