【问题标题】:Should I sanitize inputs to a parametrized query?我应该清理参数化查询的输入吗?
【发布时间】:2012-05-10 19:24:17
【问题描述】:

我有几个关于参数化查询的基本问题

考虑这段代码:

$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. 第二段代码可以吗,还是我也应该将$_GET['id'] 转换为int?
  3. 第二段代码是否存在已知漏洞?也就是说,如果我使用第二个查询,有什么方法可以进行 SQL 攻击?

【问题讨论】:

    标签: mysql sql-injection sanitization


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

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

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

      同样,第二段代码应该完全没问题——即使数据类型是字符串,MySQL 也知道不会为 SQL 评估它,因为它是一个参数,因此只能被视为文字值。但是,执行强制转换肯定没有危害(这将避免 MySQL 处理参数的任何缺陷) - 我建议两者都做。

      编辑 - @Tomalak 提出了一个很好的观点,即强制转换可能导致不正确的数据,并建议首先使用诸如is_numeric() 之类的健全性检查来验证您的输入;我完全同意。

    3. 第二段代码是否存在已知漏洞?也就是说,如果我使用第二个查询,有什么方法可以进行 SQL 攻击?

      据我所知。

    【讨论】:

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

      2. 这也太草率了。参数将作为字符串传输到数据库,数据库将尝试转换它。它是安全的(针对 SQL 注入),但除非您确切知道在传递无效数据时数据库服务器如何反应,否则您应该预先清理值(is_numeric() 和强制转换)。

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

      根据经验:

      • 不要将未经检查的数据传递到数据库并期望正确的事情发生。
      • 不要有意传递无效数据并相信其他系统会以某种方式做出反应。自己进行完整性检查和错误处理。
      • 不要“哦,这会转换为0,而且我没有ID为0的记录,所以没关系。”是你思考过程的一部分。李>

      【讨论】:

      • @eggyal 不太可能,但是是的。
      • 我担心可能的攻击,而不是输入的正确性,但这仍然是一个好点。 (但请注意 is_numeric 也允许浮动)
      • 另外,我完全同意最好的办法是从一开始就使用参数化查询,但是如果您要更新一些旧代码,这将不起作用! :)
      • @nico is_numeric() 允许浮动,但它使int() 可以产生的两个结果之间存在差异(“这是0,因为输入无效。” 和 “这是0,因为输入是'0'。”)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-18
      • 1970-01-01
      • 2016-05-28
      • 1970-01-01
      • 2016-01-28
      • 2023-01-19
      相关资源
      最近更新 更多