web-dev-qa-db-ja.com

INSERTでのSQLインジェクション

私の会社のイントラネットに小さな調査Webページを作成しました。このWebページには外部からアクセスできません。

フォームは、いくつかのラジオボタンとコメントボックスです。

適切なコーディング方法を維持し、SQLインジェクションから保護したいと思います。

SQLインジェクションは、テキストボックスからのコメントを含む挿入ステートメントで発生しますか?その場合、.NET 2.0を使用してそれを防ぐにはどうすればよいですか?

27
Brad

インジェクションは、適切に実行されないSQLステートメントで発生する可能性があります。

たとえば、コメントテーブルに整数IDとコメント文字列の2つのフィールドがあるとします。したがって、次のようにINSERTを実行します。

 INSERT INTO COMMENTS VALUES(122,'I like this website');

次のコメントの入力を検討してください。

'); DELETE FROM users; --

何も処理せずにコメント文字列をSQLに挿入しただけの場合、これにより、単一のINSERTが次の2つのステートメントになり、コメントが続きます。

INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- ');

これにより、usersテーブルからすべてが削除されます。そして、試行錯誤やさまざまなトリックを使用して、空にする適切なテーブル名を見つけることに1日を費やすことをいとわない人々がいます。 SQLインジェクション攻撃を実行する方法の説明は次のとおりです。

これを防ぐには、 パラメータ化されたSQLステートメント を使用する必要があります。

そして、これはセキュリティ上の理由だけではありません。たとえば、次のコメントを単純にSQLステートメントを作成している場合:

I'm just loving this website

アポストロフィがSQLによって閉じ引用符として解釈されるため、SQL構文エラーが発生します。

58
Dave Webb

パラメータ化されたクエリを使用して、テキストが自動的に引用されるようにします。

SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (@val1,@val2,@txt)";
command.AddParameterWithValue( "val1", value1 );
command.AddParameterWithValue( "val2", value2 );
command.AddParameterWithValue( "txt", text );

...
27
tvanfosson

SQLインジェクションは、クエリをデータベースに返すときにいつでも発生する可能性があります。ここに簡単なデモがあります:

SQLインジェクションの説明

.NET内での鍵は、Dave Webbが与えたように実行することです。文字列全体を1つのパラメーターとして送信することでインジェクションの試みを防ぎ、SQL Serverによって解釈される可能性のあるすべての文字を処理して、クエリを変更したり、追加のコマンドを追加したりします。

また、SQLインジェクションはWebアプリケーションだけでなく、あらゆるアプリケーションで発生する可能性があることを指摘しておく必要があります。そして、その内部攻撃は通常、組織にとって最もコストがかかります。攻撃が内部から発生しないと安全に想定することはできません。

3
K. Brian Kelley

準備済みステートメントを使用してSQLインジェクションを防止します。 placehoder(?)を使用すると、SQLインジェクションの脆弱性が完全に排除されます。例String sql = Select * from user_table where username = '+ request.getparameter( "username")+'; statement.executeQuery(sql);

上記のステートメントは、SQLインジェクションに対して脆弱です。

SQLインジェクションに対して安全にするため。スニペットに従って使用

String sql = Select * from user_table where username = ?; statement.setString(1、username);

0
Vivek Sharma

文字列をSQLに連結するのではなく、準備されたステートメントとパラメーターを使用することに加えて、次のことも行う必要があります。

  1. サーバー側でユーザー入力を検証およびフォーマットします。クライアント側の検証と制限は、WebScarabなどのツールを使用するか、フォームを偽装することで簡単に回避できます。

  2. データベースユーザーアカウントに適切な権限を設定します。 Webアプリケーションは、データベース内の別のアカウントまたはロールを使用し、アプリケーションの実行に必要なテーブル、ビュー、およびプロシージャのみに権限を制限する必要があります。ユーザーにシステムテーブルの選択権限がないことを確認してください

  3. ユーザーからの詳細なエラーメッセージを非表示にし、オブジェクトにはあまり一般的でない名前を使用します。サーバーの種類(Oracle、mysql、sqlserver)を特定し、基本的なスキーマ情報をエラーメッセージで見つけて、「user(s)」、「employee(s)」というテーブルから情報を取得できる頻度に驚かされます。 (2)のように権限を設定しておらず、SQL Serverでこのようなステートメントを実行できるサーバーの種類を特定できる場合

    SELECT table_name FROM information_schema.table

    EXECUTE sp_help foundTableName

0
Gary.Ray

はい、できます。クライアントがこれを送信するとしましょう:

OR 1 = 1

それはあなたにとって非常に痛みを伴うことがあります

  SELECT * FROM admin WHERE name = @name AND password = @password

あなたはこれでこれを防ぐことができます

0
boj

はい、発生する可能性があります。これを防ぐ最も簡単な方法は、SQLを手動で作成するのではなく、準備されたステートメントを使用することです。

したがって、これよりも:

String sql = 
 String.Format("INSERT INTO mytable (text_column) VALUES ( '{0}' )",
   myTextBox.Text); // Unsafe!

あなたはこのようなことをするでしょう:

String sql = "INSERT INTO mytable (text_column) VALUES ( ? )"; // Much safer

次に、テキストボックスのテキストをパラメーターとしてDbCommandに追加します。これにより、テキストボックスが自動的にエスケープされ、「?」が置き換えられます。 SQLで。

0
Eric Petroelje