i a使用Symfony
2.8项目中的Doctrine
,我想知道使用queryBuilder
的addOrderBy()
方法时是否存在SQL注入的风险:
// Order options. Real code does not specify this manually, but receives
// the options via user form input
$orderBy' = array(
'column1' => 'ASC',
'column2' => 'DESC',
...
'columnN' => 'ASC',
);
$qb = $this->em->createQueryBuilder();
...
foreach ($orderBy as $column => $orderOption) {
$qb->addOrderBy("e.$column", $orderOption);
// Does not work:
// $qb->addOrderBy("e.$column", ':orderOption')
// ->setParameter('orderOption', $orderOption);
//
// Error: Expected end of string, got ':orderOption'"
}
// Result is something like:
...ORDER BY e0_.column1 ASC, e0_.column2 DESC...
问题是,可以通过用户表单输入接收订单选项,这些输入可以操作到; DROP TABLE someTable
而不是ASC
或DESC
。
我已经尝试过,但是查询构建器似乎不接受;
分隔的多个查询,这并不意味着没有其他/更好的注射: - )
当然,可以通过过滤收到的结果并跳过所有无效的搜索选项来轻松解决问题。但是我试图理解addOrderBy()
是否通常方法。是否可以保存将任何值传递给该方法,而Doctrine
将处理其余的,还是存在潜在风险?
我想知道为什么->setParameter()
方法不起作用,就像使用->where()
时一样。
简短的答案是,通过表单提交的列名实际上可以用于SQL注入攻击。学说假设您已经正确验证了列(和表)名称。
学说代码很容易阅读,值得一提的是这些问题:
public function addOrderBy($sort, $order = null)
{
$orderBy = ($sort instanceof ExprOrderBy) ? $sort : new ExprOrderBy($sort, $order);
return $this->add('orderBy', $orderBy, true);
}
请注意,在查询中使用expr根本没有任何值。学说照顾为您生成它们。
$ this->添加更为复杂,但基本上第二个参数最终被传递而没有逃避或过滤等。
我想知道为什么 -> setParameter()方法不起作用, 使用 -> where()
重要的概念是准备的语句仅保护 values 不是列或表名。
再次,这完全取决于您从野外过滤表/列名称。查看来源可能很有帮助。
您可以使用Expr
类:http://docs.doctrine-project.org/projects/doctrine-orm/orm/en/latest/reference/query-builder.query-builder.html#the--the--the--the--the--the--the--the--the--the--the--the--the--the--the--the--the--the--the--the--the-pthe--the-projectsexpr级
或返回有效值的简单函数/方法:
function orderOption($option, $defaultOption = 'ASC') {
if (in_array(strtoupper($option), ['ASC', 'DESC']) {
return $option;
}
return $defaultOption;
}