2011-02-03 16 views
52

バックグラウンドで正確に何が起こっているのですか。SQLParameterは、.NETパラメータ化クエリでSQL Inection攻撃を防ぎますか?疑いのあるキャラクターを取り除くだけですか、それとももっと何かがありますか?SQLParameterはSQLインジェクションをどのように防止しますか?

悪意のある入力に合格したときに実際にSQL Serverに到達する内容を確認した人はいませんか?

関連:Can you use a SQLParameter in the SQL FROM statement?

答えて

54

あなたがSQLParametersを使用してSQLCommandを実行すると、基本的に、パラメータは、ステートメントに直接挿入されることはありません。代わりに、sp_executesqlと呼ばれるシステムストアドプロシージャが呼び出され、SQL文字列とパラメータの配列が与えられます。

そのようなものとして使用する場合、パラメータは単離され、データとして扱われ、代わりにステートメントから解析される有する(したがって、おそらくそれを変更すること)であるので、どのようなパラメータが含まれ「行わない」ことがないことができます。パラメータ値が何らかの形で無効であるという大きな大きなエラーが発生します。

+1

また、(この場合、およびTSQL)SQL変数をサポートしていない場所で変数を使用しようとするためにエラーが発生します。 IE: 'FROM'句、IN句でカンマで区切られたリストを表す単一のパラメータなど –

+0

これは質問に答えないと思います。 SQLParameterクラスを使用してストアドプロシージャを呼び出すことができます。SQLParameterクラスは、プロシージャにparamsを渡しますが、sp_executesqlは呼び出しません。連結されたSQL文字列のパラメータ値はどうなりますか? – Ian

9

「などSqlParameterCollectionなどのパラメータのコレクションは、型チェックと長さの検証を提供しますが、パラメータコレクションを使用する場合は、入力がリテラル値として扱われ、SQL Serverが実行可能なコードとしてそれを扱いません。パラメータコレクションを使用することのもう1つの利点は、型と長さのチェックを実施できることです。範囲外の値は例外をトリガーします。これは深い防御の良い例です。

http://msdn.microsoft.com/en-us/library/ff648339.aspx

4

パラメータ化されたクエリを使用すると、攻撃面がパラメータを使用して回避されます。

SqlParametersを使用しますが、オーバーフロー、アンダーフロー、および未検証のパラメータについては忘れないでください。たとえば、メソッドが "proc buy_book (@price money"の場合、悪意のある攻撃者は@price0.01に設定して実行するか、オーバーフローの原因となるものを送信することによってアプリケーションに何か興味深い操作を行わせようとします。 SQLオーバーフローは興味深いものにしない傾向がある(すなわち、それらはただ例外が発生し、あなたは、隣接するメモリに書き込むことができそうにない)

21

より簡単に理解し、より一般的な答えは、このように書きます:

動的SQLクエリを想像してみて:

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password

単純なSQLインジェクションがちょうどこれが効果的にSQLクエリになるだろう' OR 1=1--として

ユーザーネームを入れて次のようになります。

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password

これがtrueに等しくする、boolean型である、その名が空白('')または1=1あるすべての顧客を選択すると言います。その後、--を使用して残りのクエリをコメント化します。これにより、カスタマーテーブル全体が印刷されます。または、それを使用して何でもできます。

は今、パラメータ化クエリは、コードのように、違ったことを実行します。ユーザー名とパスワードが関連付けられているinputedユーザ名とパスワードを指し示す変数です

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?' parameters.add("User", username) parameters.add("Pass", password)

今のところ、これは何も変わらないと思うかもしれません。きっとあなたはまだだけのユーザ名フィールドに誰OR = 1' 1のようなものを入れることができます - 、効果的にクエリを作成:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'

そして、これは有効な引数のように思われます。しかし、あなたは間違っているでしょう。

パラメータ化されたクエリが動作する方法は、SQLクエリがクエリとして送信され、データベースがこのクエリが行うことを正確に認識しているだけで、ユーザー名とパスワードを単に値として挿入します。これは、データベースがすでにクエリが何をするのかを知っているため、クエリに影響を与えることができないことを意味します。したがって、この場合、ユーザ名はNobody OR 1=1'--で、空白のパスワードが検索されますが、falseになるはずです。

これは完全な解決策ではありません。入力検証はまだ実行する必要があります。などの他の問題に影響することはないので、データベースに入れても問題ありません。それがページに読み込まれると、出力の検証に応じて通常のjavascriptとして表示されます。だから実際には、入力検証を使用するのが最善ですが、パラメータ化されたクエリやストアドプロシージャを使用してSQL攻撃を止めることです。

出典:http://www.lavamunky.com/2011/11/why-parameterized-queries-stop-sql.html

+0

あなたが説明した方法を愛してください:-)きれいでポイントに。 – Sujith

関連する問題