我正在使用PDO的参数化查询来从MySQL数据库中检索具有相当复杂查询的数据。作为这样做的一部分,我使用了类似的代码:
查询:
$query = "SELECT * FROM table WHERE something = :id_$id";
$stmt = $db->prepare($query);
param绑定:
$stmt->bindParam(":id_$id", $id);
我的理解是PDO通过在调用bindParam中“清理”替换字符串来清理参数化输入,但我的问题是: 攻击者是否可以利用上述构造(通过$ id的值)来注入不受欢迎的SQL?
PDO对:id_ $ id进行文本替换,并使用$ id的清理值,因此我认为不包含任何部分:id_ $ id(无论它最终是什么)应该在最后的查询中结束,但我希望得到明确的答案!
编辑:看起来我并不像我应该解释为什么我认为可以安全的事情。当然,我并不认为这是一种良好的方式。
我认为这可能是安全的原因是PDO(如果这是错误的,请纠正我)在替换文本上进行文本替换已清理的bound-param。直观地说,这应该表明替换文本(“:id_ $ id”)可以是任何值,因为当参数放在查询中时它将完全被PDO替换。由于参数替换涉及清理参数的值,而“:id_ $ id”可能是危险的,“$ id”(这是最终查询中出现的)应该是安全的。
这是我的理由,无论如何。我的代码中没有做任何危险的事情,所以这更符合学术兴趣。
答案 0 :(得分:1)
当然它很脆弱。
但是,使用命名占位符完全是可选的。所以,您根本不必使用它们:
$query = "SELECT * FROM table WHERE something = ?";
$stmt = $db->prepare($query);
$stmt->execute(array($id));
而且,你知道,无论相当复杂的代码都可以简化。
答案 1 :(得分:-1)
pdo会对输入进行清理,您可以在bindValue / bindParam的第三个参数中进一步指定类型。我会避免使用$作为你的令牌的一部分,因为如果在“”:
中它可以被php解释$query = "SELECT * FROM table WHERE something = :id;";
$stmt = $db->prepare($query);
$stmt->bindParam(":id", $id, PDO::PARAM_INT);
这将确保如果$ id不是int pdo应该引发异常。
即使尝试以这种方式注入sql也会被转义。
答案 2 :(得分:-1)
您应该考虑为$ id使用一组封闭的允许值。我的意思是:
switch ($id) {
case "value01":
$param = ":id_01";
break;
case "value02":
$param = ":id_02";
break;
default:
// safe value
$param = ":id_00";
}
$query = "SELECT * FROM table WHERE something = $param";
$stmt = $db->prepare($query);
$stmt->bindParam("$param", $id);