我应该清理参数化查询的输入吗?

时间:2012-05-01 07:27:19

标签: mysql sql-injection sanitization

我对参数化查询有几个基本问​​题

考虑以下代码:

$id = (int)$_GET['id'];
mysql_query("UPDATE table SET field=1 WHERE id=".$id);

现在使用参数化查询同样的事情

$sql = "UPDATE table SET field=1 WHERE id=?";
$q = $db->prepare($sql); 
$q->execute(array($_GET['id']));

我的问题是:

  1. 是否存在第一个代码(即(int)演员)不安全的情况?
  2. 是第二段代码OK还是我应该将$_GET['id']转换为int?
  3. 第二段代码有任何已知的漏洞吗?也就是说,如果我使用第二个查询,是否有任何方式可以进行SQL攻击?

2 个答案:

答案 0 :(得分:3)

  1. 是否存在第一个代码(即使用(int)强制转换)不安全的情况?

    我不是PHP专家,但我认为不应该。这并不是说PHP没有可以在这里利用的错误(已知或尚未被发现)。

  2. 是第二段代码OK还是我还应该将$ _GET ['id']转换为int?

    同样,第二段代码应该绝对正确 - 即使数据类型是一个字符串,MySQL也不会为SQL评估它,因为它是一个参数,因此只能被视为文字值。但是,在执行转换时肯定没有伤害(这可以避免MySQL处理参数的任何缺陷) - 我建议同时执行这两种操作。

    编辑 - @Tomalak非常关注演员可能导致数据不正确,并建议首先使用is_numeric()等健全性检查验证您的输入;我全心全意地同意。

  3. 第二段代码有任何已知的漏洞吗?也就是说,如果我使用第二个查询,是否有任何方式可以进行SQL攻击?

    据我所知。

答案 1 :(得分:2)

    转换失败时,
  1. (int)会产生0。这可能导致更新错误的记录。此外,当后面的查询变得更复杂时,它是草率的,并且是“忘记”正确类型转换的公开邀请。
    以当前形式安装 (针对SQL注入,而不是更新错误的记录),但我仍然不推荐它。一旦查询变得更复杂,你无论如何都必须使用预准备语句,所以从一开始就这样做 - 也是为了保持一致性。

  2. 那也很邋..该参数将作为字符串传输到DB,DB将尝试将其强制转换。它是安全的(针对SQL注入),但除非您确切知道数据库服务器在传递无效数据时的反应,否则您应该预先清理该值(is_numeric()并进行转换)。

  3. 没有。 (除非PDO中存在错误,否则。)

  4. 根据经验:

    • 不要将未经检查的数据传递给数据库,并期望正确的事情发生。
    • 不要明知传递无效数据,并相信其他系统会以某种方式作出反应。自己进行健全性检查和错误处理。
    • 不要“哦,转换为0并且我没有ID 0的记录,所以没关系。”你想法的一部分过程