堆叠注入是利用数据库支持多条sql语句执行的特性,通过分号分隔在一条请求中注入并执行恶意命令。pdo默认不允许多语句执行是为了防止这种攻击,确保每次查询只返回一个结果集,从而隔离不同逻辑的sql操作。

为什么PDO默认禁止多语句执行
PDO默认设置ATTR_EMULATE_PREPARES为true,此时多语句功能被强制关闭。这是为了安全考虑,避免应用层直接暴露底层数据库的多语句能力。

try {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
// 默认情况下,即使使用模拟预处理,多语句也是禁用的
$stmt = $pdo->query("SELECT * FROM users; DROP TABLE users");
} catch (PDOException $e) {
echo $e->getMessage();
}
如何开启PDO的多语句支持
要启用多语句执行,必须将ATTR_EMULATE_PREPARES设置为false,并显式配置ATTR_STRINGIFY_FETCHES等选项。这通常需要在连接时通过DSN或setAttribute完成。

$options = [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
];
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass', $options);
$stmt = $pdo->query("SELECT * FROM users; SELECT * FROM logs");
// 此时可以获取多个结果集
while ($row = $stmt->fetch()) {
print_r($row);
}
基于具体输入条件的多语句行为验证
当输入包含分号且数据库驱动支持时,PDO会尝试解析后续语句。如果未正确配置,通常会抛出异常或忽略后续部分。实际测试表明,只有在禁用模拟预处理后,多语句才能按预期工作。

















