2016-12-07 2 views
3

I使っSymfony 2.8プロジェクト内のDoctrineと私はqueryBuilderaddOrderBy()方法使用している場合、SQLインジェクションの危険性がある場合は疑問に思う: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... 

問題があるのためのオプションは、ユーザーを介して受信されていることを、 ASCまたはDESCの代わりに; DROP TABLE someTableのようなものに操作できるフォーム入力。

は、私はすでにこれを試してみましたが、クエリビルダはもちろん

:-)他/より良い注入ができなかったことを、意味するものではありません;、で区切られた複数のクエリを受け入れていないようです受信した結果をフィルタリングし、すべての無効な検索オプションをスキップすることで、問題を簡単に解決できます。しかし、一般的にaddOrderBy()メソッドの場合、私は理解しようとしています。 メソッドに値を渡すのが節約され、Doctrineが残りを処理しますか、または潜在的なリスクはありますか?

->where()を使用する場合のように、->setParameter()メソッドが機能しないのはなぜかと思います。

答えて

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はあなたのためにそれらを生成します。 > setParameterを()メソッドは動作しません - なぜ私が疑問に思う

ます$ this->追加は

などもう少し複雑ですが、基本的には2番目の引数は終わるがエスケープやフィルタリングなしと一緒に渡されていますそれは 使用する場合と同様に、 - >ここで、()

重要な概念は、準備された文のみない列またはテーブル名を保護することです。

また、野生のテーブル/カラム名をフィルタリングすることは、あなた次第です。ソースを見ることは参考になります。

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; 
} 
+0

ありがとうございますが、質問で説明したように、保存フィルタ機能を探すのではなく、最初に 'addOrderBy()'が危険にさらされているかどうかについてです。 –

+0

だから、 'Expr'を使ってください。 – rogeriolino

+0

私は 'Expr'を使いたくありません:)' addOrderBy() 'を使う上でリスクがあるかどうかを知りたいのですが.. –

関連する問題