Doctrine queryBuilder:addOrderBy()方法中的SQL注入风险?

And*_*ord 4 php sql-injection symfony doctrine-orm

Doctrine在一个Symfony2.8项目中使用,我想知道在使用以下addOrderBy()方法时是否存在SQL注入的风险queryBuilder:

// 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...
Run Code Online (Sandbox Code Playgroud)

问题是,订单选项是通过用户表单输入接收的,可以将其操作为类似; DROP TABLE someTable而不是ASCDESC.

我已经尝试过这个,但查询构建器似乎不接受多个查询分隔;,这并不意味着没有任何其他/更好的注入:-)

当然,通过过滤收到的结果并跳过所有无效的搜索选项,可以很容易地解决问题.但我试图了解,如果addOrderBy()方法一般.是保存将任何值传递给方法Doctrine并将处理其余的,还是存在潜在风险?

我想知道为什么这个->setParameter()方法不起作用,就像使用时一样->where().

Cer*_*rad 7

简短的回答是,表单提交的列名实际上可以用于SQL注入攻击.Doctrine假定您已经正确验证了列(和表)名称.

该学说代码相当容易阅读,值得一看这些问题:

public function addOrderBy($sort, $order = null)
{
    $orderBy = ($sort instanceof Expr\OrderBy) ? $sort : new Expr\OrderBy($sort, $order);

    return $this->add('orderBy', $orderBy, true);
}
Run Code Online (Sandbox Code Playgroud)

请注意,在查询中使用Expr时根本没有任何价值.Doctrine负责为您生成它们.

$ this-> add有点复杂,但基本上第二个参数最终被传递,没有转义或过滤等.

我想知道为什么 - > setParameter()方法不起作用,就像使用 - > where()时一样

重要的概念是预准备语句只保护而不是列名或表名.

因此,完全由您来过滤来自野外的表/列名称.并且查看来源可以提供信息.