2015-10-15 19 views
7

私は、ProjectIdProjectNameの2つのカラムを持つProjectテーブルを持っていて、SqlCommandを構築して実行する関数を書いて、指定された名前のプロジェクトのIDをデータベースに問い合わせます。このコマンドは動作しますが、SQL Injectionに対して脆弱です:なぜString.Formatは機能しますが、SqlCommand.Parameters.Addは機能しませんか?

string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}", 
      attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue)); 

SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection); 
using (SqlDataAdapter adapter = new SqlDataAdapter(command)) 
{ 
    DataTable attributes = new DataTable(); 
    adapter.Fill(attributes); 
    ... 
} 

attributeParamtableParamidParam、およびidValueはすべて文字列です。たとえば、それぞれ"ProjectId","Project","ProjectName"、および"MyFirstProject"とすることができます。 surroundWithSingleQuotes''の文字列を囲んでいるため、surroundWithSingleQuotes(idValue) == "'MyFirstProject'"です。私は可能な限り一般的なこの関数を記述しようとしています。なぜなら、将来、あるテーブルから特定の属性をすべて取得したいからです。

上記String.Formatのは動作しますが、これはない:

string sqlCommand = String.Format("SELECT @attributeparam FROM {0} WHERE " + 
    "@idparam = @idvalue", tableParam); 

command.Parameters.Add(new SqlParameter("@attributeparam", attributeParam)); 
command.Parameters.Add(new SqlParameter("@idparam", idParam)); 
command.Parameters.Add(new SqlParameter("@idvalue", 
    surroundWithSingleQuotes(idValue))); 

SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection); 
using (SqlDataAdapter adapter = new SqlDataAdapter(command)) 
{ 
    DataTable attributes = new DataTable(); 
    adapter.Fill(attributes); 
    ... 
} 

私がなぜわかりません。エラーメッセージは表示されませんが、SqlDataAdapterを使用してDataTableを入力すると、DataTableには何も含まれません。

  • this answerMicrosoft's documentation後、AddWithValueを使用したりParameters.AddSqlParameter.Valueを使用して:ここで私は無駄に、撮影した様々なアプローチがあります。
  • 選択的に実際の値又はパラメータ文字列のいずれかで{0}{1}{2}、及びString.Format{3}を置き換えます。

私のコードの他の場所では、パラメータ化されたクエリを使用しましたが(パラメータは1つのみ)、問題はありません。

+2

唯一のパラメータは '{3}'です。 –

+2

列の名前にパラメータを使用することはできません。テーブル名の場合と同じように 'string.Format'を使用する必要があります。 – juharr

答えて

7

SQLの基本的なパラメータは、の場合にのみ有効です。カラムまたはテーブルの識別子ではありません。あなたの例では、最後のパラメータだけが値を表します。

カラム名とテーブル名を動的にする必要がある場合は、SQLのその部分を自分で構築する必要があります。 SQLインジェクション攻撃に関連するすべての通常の理由に対して、には非常に注意してください。理想的には、テーブルと列の値の既知のホワイトリストのみを許可します。より一般的にする必要がある場合は、非常に限定的な検証を実行することをお勧めします。quote the identifiersは、キーワードとの競合を避けるため(または理想的にはそれらを完全に禁止する)です。

もちろん、値にSQLパラメータを使用してください。

+0

非常に役に立ちました - ありがとうございました! – rln

0

これは有効な文です: SELECT * FROM SomeTable WHERE [email protected]

これがないのに対し: SELECT * FROM @param

これを使用すると、テーブル名、ビュー名、カラム名などの値のパラメータを使用していないことを意味し

関連する問題