0

我正在使用带有 PDO 的参数化查询来从具有相当复杂查询的 MySQL 数据库中检索数据。作为这样做的一部分,我使用了一些类似的代码:

查询:

$query = "SELECT * FROM table WHERE something = :id_$id";
$stmt = $db->prepare($query);

参数绑定:

$stmt->bindParam(":id_$id", $id);

我的理解是,PDO 通过在调用 bindParam 时“清理”替换字符串来清理您的参数化输入,但我的问题是: 攻击者是否可以利用上述构造(通过 $id 的值)来注入不需要的 SQL ?

PDO 在 :id_$id 上用 $id 的清理值进行文本替换,所以我认为:id_$id 的任何部分(无论它最终是什么)都不应该出现在最终查询中,但我很想得到一个明确的答案!

编辑:看起来我并没有像我应该解释的那样清楚为什么我认为这可能是一件安全的事情。当然,我不建议这是做事的好方法。

我认为这可能是安全的原因是 PDO(如果这是错误的,请纠正我)对替换文本上的已清理绑定参数进行文本替换。直观地说,这应该表明替换文本 (":id_$id") 可以是任何值,因为当参数放在查询中时它将完全被 PDO 替换。由于参数替换涉及清理参数的值,而 ":id_$id" 执行起来可能很危险,"$id"(出现在最终查询中)应该是安全的。

无论如何,这是我的推理。我没有在我的代码中做任何危险的事情,所以这更像是一种学术兴趣。

4

3 回答 3

1

当然是脆弱的。

但是,使用命名占位符是完全可选的。因此,您根本不必使用它们:

$query = "SELECT * FROM table WHERE something = ?";
$stmt = $db->prepare($query);
$stmt->execute(array($id));

而且,你知道,任何相当复杂的代码都可以被简化。

于 2013-05-14T05:56:54.023 回答
-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);
于 2013-05-14T06:06:00.847 回答
-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 也会被转义。

于 2013-05-13T19:59:35.343 回答