是否真的需要对来自另一个查询的可信数据进行准备的语句?

时间:2018-08-22 06:54:20

标签: php pdo prepared-statement

在处理从另一个查询中获取的可信数据时,是否需要准备好的语句?

例如。
用户在整个站点中导航时,他们单击如下命名的链接:/?category=health,其中health是发送到数据库的值。
在这种情况下,我当然使用如下准备好的语句:

$qry = $dbh->prepare('SELECT category_id, and, other, columns FROM categories WHERE query_value = ?');
$qry->execute([$_GET['category']]);
$get = $qry->fetch();
$qry = null;

但是在脚本的更下方,我将基于从上一个查询中获取的categories.category_id显示与所选类别相关的内容。

$Banners = $dbh->query('SELECT image FROM Banners WHERE category_id = '.$get['category_id'])->fetchAll();

我想这是一个安全的查询。
该值不能不是受信任的值,因为它必须是前一个查询的结果?
如果先前的查询未返回true,则不会执行此查询。

到目前为止,这是我的做法:
这是3排线。但是,如果我确定上面的1-liner也可以的话,它会加快编码部分的速度。

$qry = $dbh->prepare('SELECT image FROM Banners WHERE category_id = ?');
$qry->execute([$get['category_id']]);
$Banners = $qry->fetchAll();

1 个答案:

答案 0 :(得分:2)

这主要是关于确保您的SQL语法是合理的以及您认为的语法是什么。防止恶意攻击只是其必然结果。如果将来您的类别ID产生撇号或其他不属于常规值的内容怎么办?无论如何,您都需要转义以获取正确的语法,或者更好地是准备好的语句。

其次,存在二阶注入,其中先前被视为不安全的值现在突然被视为安全,即使它仍然具有攻击的可能性。例如。如果您的值合法包含撇号。

更广泛地说:如何确保值是“安全的”?

// $get['category_id'] is safe and doesn't need escaping
'SELECT image FROM Banners WHERE category_id = '.$get['category_id']

好吧,你怎么知道的?哪些代码可确保此值安全?这个价值从何而来?您确定是它的来源吗?您要将此处查询的完整性外包给代码的其他部分。您如何确保其他部分正确地工作?现在,还是将来,经过大量重构? 通过以安全的方式编写查询来确保自己在生成正确的查询,不要将安全性外包。

您需要问自己:此查询是否易于按其编写方式进行注入?上面示例的答案是简单的,它是$get['category_id']是您所认为的信任。