64

クエリ 1 と 2 の両方で、テキスト ボックスのテキストがデータベースに挿入されます。ここでのパラメーター化されたクエリの重要性は何ですか?

  1. txtTagNumberクエリ パラメータとして渡す

    SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
    cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
    cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
    
  2. txtTagNumberクエリを作成する前に整数に変換する

    int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
    INSERT into Cars values(tagnumber.Text); /* then is it the same? */
    

また、ここでは、正規表現の検証を使用して、不正な文字の挿入を停止します。

4

6 に答える 6

55

パラメータ化されたクエリは、SQL クエリを実行する前に、引数の適切な置換を行います。「汚い」入力がクエリの意味を変える可能性を完全に排除します。つまり、入力に SQL が含まれている場合、SQL が結果のステートメントに挿入されないため、実行されるものの一部になることはできません。

于 2011-03-29T05:54:26.413 に答える
30

動的 SQL クエリを想像してみてください

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

したがって、単純なSQLインジェクションは、ユーザー名を入力するだけです。' OR 1=1--これにより、SQLクエリが効果的に作成されます。

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

これは、ユーザー名が空白 ('') または 1=1 であるすべての顧客を選択することを示しています。これはブール値であり、true に相当します。次に -- を使用して、残りのクエリをコメントアウトします。したがって、これはすべての顧客テーブルを出力するか、必要なことを何でも行います。ログインする場合、最初のユーザーの権限でログインします。これは多くの場合、管理者です。

パラメータ化されたクエリは、次のようなコードを使用して、別の方法で実行します。

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'

parameters.add("ユーザー", ユーザー名) parameters.add("パス", パスワード)

username と password は、関連する入力されたユーザー名とパスワードを指す変数です

この時点で、これで何も変わらないと思うかもしれません。確かに、ユーザー名フィールドに「Nobody OR 1=1'--」のようなものを入力して、効果的にクエリを作成することもできます。

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

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

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

ソース: lavamunky.com; 2011年11月

于 2016-12-21T20:49:34.927 に答える
23

可能性のあるパラメーターに sql が含まれていて、文字列が適切に処理されない場合、SQL インジェクションが発生します。

例えば:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + condition+''";

条件は、リクエスト内のユーザーからの文字列です。悪意のある状態の場合は、次のように言います。

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + "a' ;drop table  mytable where '1=1"+"'";

悪意のあるスクリプトを実行する可能性があります。

ただし、パラメーターを使用すると、文字列文字をエスケープする可能性のある文字が入力から消去されます...

何が入っても、注入スクリプトを実行できないことを確認できます。

実際に実行された SQL は次のようになります。

select * from mytable where rowname = 'a'';drop table mytable where 1=1'''

本質的には、rowname = a';drop table mytable where 1=1' の行を探し、残りのスクリプトを実行しません。

于 2011-03-29T06:11:13.737 に答える
3

パラメータ化されたクエリがすべてを処理します。

パラメーター化されたクエリを使用すると、一般的なインジェクションに加えて、処理されるすべてのデータ型、数値 (int および float)、文字列 (埋め込み引用符付き)、日付と時刻 (.ToString() が呼び出されない場合、フォーマットの問題やローカリゼーションの問題は発生しません) を取得します。インバリアント カルチャで、クライアントが予期しない日付形式のマシンに移動します)。

于 2011-03-29T06:01:25.927 に答える
1

パラメーター化されたクエリを使用すると、クライアントはクエリ テキストとは別にデータを渡すことができます。テキストがほとんどない場合は、検証とエスケープを行います。もちろん、パラメータ化は他の種類のインジェクションに対しては役に立ちませんが、パラメータは個別に渡されるため、実行テキスト クエリとしては使用されません。

よく似ているのは、最近のほとんどのプロセッサとオペレーティング システムでバッファ オーバーフローから保護するために使用される「最近の」実行ビットです。バッファ オーバーフローは引き続き許可されますが、挿入されたデータの実行は妨げられます。

于 2011-03-29T06:11:02.243 に答える
1

人がそう感じる理由はよく理解できます。

sqlQuery = "select * from users where username='+username+';"

sqlQuery = "select * from users where username=@username;"

上記のクエリはどちらも同じことをしているように見えますが、実際にはそうではありません。

前者は入力をクエリに使用し、後者はクエリを決定しますが、クエリの実行中に入力をそのまま置き換えるだけです。

より明確にするために、パラメーターの値は、変数のメモリが格納されているスタック上のどこかに配置され、必要に応じて検索に使用されます。

したがって' OR '1'='1、ユーザー名の入力として与える場合、前者は動的に新しいクエリまたはクエリを作成し、SQL クエリ文字列の一部としてsqlQuery実行します。

同じ入力に対して、後者はクエリ文字列で静的に指定されたクエリを使用してテーブル' OR '1'='usernameフィールドを検索しますuserssqlQuery

それを統合するために、これはパラメーターを使用してクエリを作成する方法です。

SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);

SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@username";
parameter.Value = "xyz";

command.Parameters.Add(parameter);
于 2016-03-17T09:40:34.240 に答える