web-dev-qa-db-ja.com

単純な正規表現でSQLiを100%検出することは可能ですか?

単純な正規表現を使用して、可能なSQLi攻撃を100%検出できるかどうか疑問に思っています。

言い換えれば、非常に単純なPHPコードを例として使用します:

if (preg_match("/select/i", $input)) {
    attack_log("Possible SELECT SQLi detected.")
}

質問は次のとおりです。

  • その正規表現は、SELECTを使用するすべての可能なSQLi攻撃をキャッチしますか?そうでない場合、その正規表現を変更して、SELECTに依存するすべての注入を検出できるようにすることは可能ですか?
  • 可能性のあるすべてのSQLiをキャッチできるようにその正規表現をに変更することは可能ですか?SELECTステートメントだけでなく、残りのすべてもキャッチできますか?これを実現するには、 "-"と "OR"を含むevery可能なSQLキーワードを正規表現に追加する必要があると思います。
  • 考えられるすべてのSQLキーワードを照合することによってすべてのSQLiを検出することが不可能または実現不可能である場合、考えられる攻撃の大部分を検出できるようにするキーワードの限定されたサブセットはありますか?
37
reed

SQLiのキーワードフィルタリングは良い手法ではありません。それをバイパスする方法は多すぎます。

たとえば、_sel/**/ect_のようなクレイジーなものが機能する可能性があります。または、substr()を使用してゲームをプレイします。そしてEXEC('SEL' + 'ECT 1')があります。

一般的なフィルタリング技術を回避する方法については、 多くのガイド があります。

ただし、フィルタリングするもののスーパーセット(selectと_/**/_とsubstrEXEC)があるかどうかを尋ねるかもしれませんが、リストは非常に、非常に長く、それでも包括的なリストを取得できない場合があります。

より適切なアプローチは、許容可能な入力の範囲を理解してそれらを保護するか、適切な設計を通じてSQLiを無効にすることです。

169
schroeder

番号

すべてのSQLインジェクションは(定義により)有効なSQLであり、SQLは文脈自由言語( source )であるため、SQLインジェクションと一致し、試行できる正規表現は(定義により)ありませんこれを行うと、おそらく this のような結果が得られます。

ほとんどすべてのコメントで述べられているように、仕事に適したツールを使用してください。この場合、それは準備されたステートメントです。

106
Sefa

技術的には、これは完全に可能です(そうするとデータベースが役に立たなくなります):

  • .+確かにSQLiをすべて検出します

ただし、通常のクエリを実行しようとする試みも検出されます(または任意のテキスト)、データベースを完全に無用にする

同様に、データベースをオフにするとSQLiから保護できると言えます。それは本当ですが、それはまたそれが意図された目的のためにデータベースを役に立たなくします。

準備されたステートメントまたはパラメーター化されたクエリを使用します。彼らはこの問題を解決するために存在します。

58
Fake Name

単純な正規表現を使用して、可能なSQLi攻撃を100%検出できるかどうか疑問に思っています。

この方法で質問しているという事実は、問題について誤って考えていることを示しています。

SQLインジェクションはdataの脆弱性ではありません。これはアプリケーションの脆弱性ですcode that handles that data。

例:現在、「SQLインジェクション」をWebサイトのテキストエリアに入力しています!そして、「-DROP TABLE Users;ここ!私の答えはSQLインジェクション攻撃ですか?もちろん違います。

さて、あなたがやろうとしていることは、試みられた SQLインジェクション攻撃を検出することだと主張することができます。しかし、ここで、入力のintentを決定する必要があります。フィールドに裸のアポストロフィを入力した場合、それはタイプミスですか、それともSQLインジェクション攻撃の試みですか?私の意図を100%検出できますか?もちろん違います。

基本的に、可能攻撃を特定しようとすると、検出率が100%になることはありません。

SQLインジェクションの脆弱性はコードにのみ存在し、データには存在しないため、データのみを考慮した分析では、せいぜい非常に大きな誤検知率が発生します。実際のすべての攻撃トラフィックに一致する可能性がある、あなたが考案したソリューションは、このWebサイトへの非常に大量のlegitimateトラフィックを、そのような攻撃が意図されていない「攻撃」として解釈します。

23
Daniel Pryden

いいえ。まず、SQLインジェクションを使用して、悪意のあるユニバーサルパスワード' OR '1' = '1や一般的なユーザー名 Robert'); DROP TABLE Students;-- 。また、「選択」は英語で非常に一般的な単語であり、さまざまな状況で完全に無害な方法で表示される場合があります。したがって、/select/iに一致する入力をフィルタリングすると、大量の誤検知が発生します(たとえば、16件の誤検知と、現在読んでいるWebサイトだけでカウントされます)。

データベースにデータを送信する前に入力をサニタイズしたい場合、 PHPにはその目的のための便利な機能があります (これらはmySQLの機能です)、他のデータベースAPIは、特定のデータベースに合わせて調整された同様の機能を提供する必要があります構文)。

しかし、特定の入力をブロックすることでSQLインジェクションから身を守ろうとすると、間違った最前線で戦います。文字列連結によるSQLステートメントの作成を停止することにより、SQLインジェクションから身を守る方がはるかに賢明です。 SQLインジェクションを意図せずに作成することを困難にする方法でデータベースと対話する一般的な代替方法は次のとおりです。

  • SQLクエリを書き込むORMラッパーを使用する
  • パラメーター化されたクエリ(準備されたステートメントとも呼ばれます)を使用する
  • SQLが言語構文の一部であるプログラミング言語を使用する
  • ストアドプロシージャを使用する
9
Philipp