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

时间:2016-12-07 13:56:28

标签: php symfony doctrine-orm sql-injection

我在Doctrine 2.8项目中使用Symfony,我想知道在使用addOrderBy()的{​​{1}}方法时是否存在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... 而不是; DROP TABLE someTableASC

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

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

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

2 个答案:

答案 0 :(得分: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);
}

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

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

  

我想知道为什么 - > setParameter()方法不起作用   当使用 - > where()

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

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

答案 1 :(得分:1)

您可以使用Expr课程:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html#the-expr-class

或者返回有效值的简单函数/方法:

function orderOption($option, $defaultOption = 'ASC') {
    if (in_array(strtoupper($option), ['ASC', 'DESC']) {
        return $option;
    }
    return $defaultOption;
}