1

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

考虑这段代码:

$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 攻击?
4

2 回答 2

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

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

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

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

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

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

    据我所知不是。

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

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

  3. 不。(除非 PDO 中存在错误,否则就是这样。)

根据经验:

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