2

私は現在、ユーザー入力で SQL クエリを構築するアプリケーションを構築していないため、この質問は単に教育目的のためのものです。

そうは言っても、ADO.NET では、次のようなことを行うことで SQL インジェクションを防ぐことができることを知っています。

OleDbCommand command = new OleDbCommand("SELECT * FROM Table WHERE Account = @2", connection);
command.Parameters.AddWithValue("@2", "ABC");

しかし、ユーザーが実際にテーブルの名前を入力できるようにアプリケーションが設計されていると仮定すると、次のことができますか? (ユーザーがテーブルの名前を指定できるようにするのが悪い考えであるかどうかは気にしません。次のことが可能かどうかを知りたいだけです...)

OleDbCommand command = new OleDbCommand("SELECT * FROM @1 WHERE Account = @2", connection);
command.Parameters.AddWithValue("@1", "Table");
command.Parameters.AddWithValue("@2", "ABC");

2 番目のコードを実行すると、SQL クエリが不完全であるという例外が発生し続けます。問題は、実行しようとしていることが単純に実行できないことなのか、それとも何かを見落としているのか疑問に思っていました。

4

1 に答える 1

4

いいえ、 SQL ステートメントの1 つのスカラー値をクエリ パラメータで置き換えることができます。
たとえば、単一の文字列リテラル、日付リテラル、数値リテラルなどです。

WHERE 句にある必要はありません。SQL で式を使用できる場所ならどこでも、スカラー値を含めることができるため、パラメーターを含めることができます。たとえば、結合条件、選択リスト、ORDER BY または GROUP BY 句などです。

次のクエリ パラメータは使用できません

  • テーブル識別子
  • 列識別子
  • SQL キーワード
  • SQL式
  • 値のリスト (IN() 述語など)

クエリのこれらの部分のいずれかをユーザーが定義できるようにする必要がある場合は、アプリケーション変数を補間または連結して SQL クエリ文字列を作成する必要があります。これにより、SQL インジェクションに対する防御が困難になります。

その場合の最善の防御策は、SQL 文字列に挿入しても安全な特定の値をホワイトリストに登録することです。たとえば、コードで定義するテーブル名のセットです。ユーザーがこれらの事前承認された値からテーブルを選択できるようにしますが、実行する SQL コードでユーザーの入力を逐語的に使用しないでください。

ユーザー入力は値を提供する場合がありますが、コードを提供するべきではありません。

私のプレゼンテーションSQL Injection Myths and Fallaciesが役に立つかもしれません。そのプレゼンテーションでホワイトリストについて説明します (私の例は PHP ですが、この考え方はどのプログラミング言語にも当てはまります)。

于 2012-11-03T17:52:45.493 に答える