web-dev-qa-db-ja.com

C#でSqlServerの単純なSQLクエリをエスケープする方法

SQL文字列を予期するAPIを使用します。ユーザー入力を取得し、エスケープしてAPIに渡します。ユーザー入力は非常に簡単です。列の値を要求します。そのようです:

string name = userInput.Value;

次に、SQLクエリを作成します。

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
                           name.replace("'", "''"));

これで十分ですか?そうでない場合、列の値を安全にする単純なライブラリ関数があります:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
                           SqlSafeColumnValue(name));

APIはデータベースとしてSQLServerを使用します。

72
sc45

SqlParameterの使用はオプションではないため、文字列リテラルの 'を' '(二重引用符ではなく、2つの単一引用符)で置き換えるだけです。それでおしまい。

ダウンボーターになるには:質問の最初の行を読み直します。 「パラメータを使用する」ことも私の腸の反応でした。

編集:はい、SQLインジェクション攻撃について知っています。この引用がそれらに対して脆弱であると思われる場合は、実用的な反例を提供してください。そうではないと思います。

121
Seva Alekseyev

Sqlパラメーターを使用するのが最善ですが、クエリの2300パラメーターに制限があります。ほとんどの場合、これで十分です。しかし、まれに、この制限を超えた場合、これはオプションとして表示されます。

0
charino

破損のリスクとテストを最小限に抑えながら、大量のアドホックSQLの問題に短時間で対処する必要がある場合は、パラメーター化する代わりに 'を' 'に置き換えることができます。

0
Alex

SqlCommandとEntity Frameworkはexec sp_executesql...を使用します。

したがって、おそらく独自のエスケープパターンを持つ生の文字列に代わるものがあります。 SqlCommandでは、技術的にパラメーター化されたクエリを使用していますが、基になるSQLコードのADO.Net抽象化をバイパスしています。

したがって、コードはSQLインジェクションを妨げませんが、究極の答えはSqlCommandではなくsp_executesqlです。

そうは言っても、sp_executesqlを使用するSQLインジェクション防止文字列を生成するには、特別な処理要件があると確信しています。

参照: 動的SQLストアドプロシージャからEntity Frameworkに値を返す方法?

0
Todd

私は検索機能に動的SQL(射撃隊がライフルをロードしているのが聞こえます)を使用していましたが、ユーザーが「O'Reilly」のような姓を持つ誰かを検索すると必ず壊れます。

私は回避策を見つけました(「ハック」を読んでください):

SQLでスカラー値関数を作成し、単一引用符を2つの単一引用符に置き換え、問題のある単一引用符を効果的にエスケープしました。
"... Surname LIKE '%O'Reilly%' AND ..."は、 "... Surname LIKE '%O''Reilly%' AND ..."になります。

この関数は、フィールドに一重引用符が含まれている可能性があると疑われる場合、sql内から呼び出されます。つまり、firstname、lastnameです。

CREATE FUNCTION [dbo].[fnEscapeSingleQuote]
    (@StringToCheck NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @Result NVARCHAR(MAX)
    SELECT @Result = REPLACE(@StringToCheck, CHAR(39), CHAR(39) + CHAR(39))
    RETURN @Result
END

あまりエレガントでも効率的でもありませんが、ピンチのときに機能します。

0
ThurstonFord