虽然 PDO 文档表明准备语句消除了手动参数引用的需要,但答案是微妙的“是” ”。 PDO 默认模拟 MySQL 的准备语句,这种模拟有时会产生可利用的漏洞。
当连接编码涉及特定的易受攻击的字符集(例如 gbk)时,就会出现潜在的漏洞, cp932) 且满足以下条件:
在这种情况下,攻击者可以制作包含无效多字节字符的有效负载,并利用客户端上的预期字符集与连接的实际字符集之间的差异。这允许他们将不带引号的字符注入到生成的查询字符串中,从而导致潜在的 SQL 注入。
预防:
缓解:
以下代码片段说明了安全实践:
// PDO without emulated prepares $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(array("xbf' OR 1=1 /*")); // PDO with DSN charset parameter $pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=gbk', $user, $password); $stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $stmt->execute(array("xbf' OR 1=1 /*")); // MySQLi (always uses true prepared statements) $mysqli->query('SET NAMES gbk'); $stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1'); $param = "xbf' OR 1=1 /*"; $stmt->bind_param('s', $param); $stmt->execute();
如果正确使用并与安全实践结合使用,PDO 准备语句可以有效防止 SQL 注入。避免易受攻击的编码、禁用模拟准备或启用 NO_BACKSLASH_ESCAPES 模式以减轻潜在漏洞至关重要。
以上是PDO 准备语句真的能免受 SQL 注入攻击吗?的详细内容。更多信息请关注PHP中文网其他相关文章!