Zend FrameworkのSQLモデルを使用する場合のSQLインジェクションの脆弱性


15

テーブルを結合するとき、Zend FrameworkのSQLモデルを使用します。例として、実際のコードを変更しましたが、ポイントが得られると思います。

$this->getSelect()->join(
                      array('sections' => $sectionsTableName),
                      'main_table.banner_id = pages.banner_id',
                      array()
                    )
                  ->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
                  ->group('main_table.banner_id'); 

ページはajaxでロードされ、$ sectionパラメーターはGETパラメーター(www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com)として送信されます。

誰かが次のようなことを実行した場合の問題は次のとおりです。

www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

このようにして、ユーザーはデータベース全体をダンプできます。データは表示されませんが、SQLはダンプを実行するため、SQLのオーバーロードが発生する可能性があります。

質問:

  1. そのようなシナリオを防ぐ最良の方法は何ですか?
  2. 今、私は以前の顧客を心配しています。このコードを使用すると、テーブルの更新や変更など、さらにリスクの高いアクションを実行できますか?DELETEがsql構文エラーを生成するように、SELECT以外のステートメントをsubselect内に配置できないためだと思います。私は正しいですか?

更新: 私の例は、$セクションの周りに記号があり、したがって注入を行うことができないため、SQL注入の適切な図ではありません。とにかく、これは整数値を期待するとき、および整数入力をフィルタリングしないときに可能です。以下の私のコメントをご覧ください。


1
あなたが使用することができます: $db = Mage::getSingleton('core/resource')->getConnection('core_read');そして$db->quote()あなたの場合でさえ見てください$db->quoteInto$thisがリソースの場合、実行できます:$this->getConnection('core_read')->quoteInto()それがコレクションの場合、実行できます$this->getResource()->getConnection('core_read')->quoteInto()。それらの線に沿って。それがあなたの目標に向かってあなたを導くのに役立つなら。
アッシュ

このシナリオは、値が整数の場合にのみ可能であることに気付きました。値がvarcharである場合、常に'符号の前に(符号があり、したがって、(SELECTまたは他のものは文字列であり、機能しません。フィールドが整数の場合、'必要はなく、そのようなシナリオが可能になります。ただし、整数は常にフィルタリングする必要があるintval()ため、これも問題になりません。
ジョニーフリー

を閉じることから始めるとどうなります'か?だから' AND (SELECT ...) '?ちなみに、Zendがこれを引用していないとは思わない...そして、バインディングを使用すると、PDOがこれを処理します。このような刺し刺した連結を決して使用しないで"sections.section= '$section'"
ください。– 7ochem

@ 7ochemそのような場合、?を使用してパラメーターをバインドする必要があります。そして 'は\になります。あなたが値整数使用している場合しかし、あなたはINTVAL()PHP関数を使用して、それをきれいにすることができるので、あなたはそれをバインドしていないと「何かが0になります
JohnyFree

回答:


8

入力を検証してください!

できるだけ良いものを。

検証のためのいくつかの提案:

  1. GETパラメーターで取得した変数の長さを確認してください。終わりのない長い文字列を受け入れる必要はありません。

  2. ドメイン名を検証します。予想されるドメイン名にはどのような形式がありますか?常にwww.mydomain.tldですか?一致または(より良い)使用をチェックする正規表現を作成しますZend_Validate_Hostname

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. ホワイトリスト:どのドメイン名が期待できるか知っていますか?許可されたドメインのリストを作成し、それらをチェックできます。残りをドロップします。

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. ドメイン名および/または文字をブラックリストに登録する:ドメイン名が必要な場合、az、0-9、および「。」以外の文字を受け入れる必要はありません。(特別なドメイン名を使用している場合を除く)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.