2017-08-23 13 views
0

私は、次の手順を作成しました:私は混乱していますパラメータ化されたSQLとストアドプロシージャについては、動的SQLを持っているそれらは同じですか?

CREATE PROC dynamicColumnsWithCheck 
(
    @colName VARCHAR(MAX), 
    @colCheck VARCHAR(MAX), 
    @condition VARCHAR(MAX) 
) 

AS 

BEGIN 

    DECLARE @sqlString NVARCHAR(MAX) 

    SET @sqlString = N'SELECT ' + @colName + ' FROM Student WHERE ' + @colCheck + ' = ''' + @condition + '''' 

    EXEC sp_executesql @sqlString 

END 

それは私のために完璧に動作しますが、私の質問は、このパラメータ化されたSQLです、ということでしょうか? またはそれは危険な動的SQLですか? SQLインジェクションについて調べて学習した後、この手順のセキュリティについて混乱します。

答えて

2

それは次のように注入してもよい:

declare @sqlstring varchar(MAX) 
    declare @colName varchar(500) = 'Password' 
    declare @colCheck varchar(500) = 'StudentName' 
    declare @condition varchar(500) = 'Zeebo'' or ''''=''' 

    SET @sqlString = N'SELECT ' + @colName + ' FROM Student WHERE ' + @colCheck + ' = ''' + @condition + '''' 


    PRINT (@sqlString) 

結果:StudentName = 'Zeebo' または '' = '学生FROM

SELECTパスワード'

''=''意志常に真実であると評価されるので、それはあなたにすべてのものを返すでしょう、それはユーザのパスワードのために災害になるでしょう。

SQLインジェクションを避ける簡単な方法は、ユーザー変数を文全体とは別の単位として扱うことです。たとえば、QuoteNameを使用してユーザー変数をラップすると、動的部分は入力としてのみ解析され、クエリ全体には影響しません。例えば

declare @sqlstring varchar(MAX) 
     declare @colName varchar(500) = 'Password' 
     declare @colCheck varchar(500) = 'StudentName' 
     declare @condition varchar(500) = 'Zeebo'' or ''''=''' 

     SET @sqlString = N'SELECT ' + QUOTENAME(@colName) + ' FROM Student WHERE ' + QUOTENAME(@colCheck) + ' = ''' + QUOTENAME(@condition) + '''' 

戻る前の注入方法を使用するには、@conditionのためのユーザ入力は、最終的な@sqlStringを構築する上でどんな役割を果たしていない、PUREの文字列として扱われます。 そして、その結果は次のようになります。でも、正しいSQLステートメントではありません[StudentName] = '[Zeebo' や '' = ']学生FROM

SELECT [パスワード]'

+0

ああ!私はちょうどあなたの注射を試み、それは働いた QUOTENAMEが働いたおかげで男。 しかし、私はC#テキストボックスからこの注入を試みたが、うまくいかなかった。 方法はありますか? –

+0

ダイのように 'Linq'を試してみてください、主なアイデアは同じです。そして、あなたが持っているエラーメッセージに基づいて注入欠陥をテストすることができます。 – LONG

0

このパラメータ化されたSQLはありますか?またはそれは危険な動的SQLですか?

両方です。

SQL Serverパラメータは、クエリのみに離散置き換えるために使用することができます - 動的SQLは、まだものですなぜあなたはオブジェクト識別子(例えば、テーブル名、カラム名)またはある句(例えばWHERE述語)をparameteriseすることはできません。

この問題のため、実行時に定義されたクエリの安全な構築を可能にする方法でSQLを安全に生成するLinq-to-Entities(Entity Framework)などのORMに目を向けている人が多くいます。

それはあなた自身のSQLを生成しようとしているよりも、LINQの中WHERE句を変更することがはるかに簡単です:SQLを自分で生成することにより、以下、このクエリをやってみ

- それはたくさん読みにくくなり、保守性、およびあなたは注射脆弱性のリスクを実行する連結を使用して直接SQLを生成するだけで簡単に実行できます:

String GetUserName(String emailAddress) { 

    IQueryable<User> query = database.Users; 
    query = query.Where(u => u.Email == emailAddress); 

    if(!userHasPermissionToViewAllUsers) { 
     query = query.Where(u => u.UserId == currentUserUserId); 
    } 

    return query.FirstOrDefault()?.UserName; 
} 
+0

ありがとう! これは素晴らしいですが、私は少し初心者です。 とにかく、試してみましょう。 LINQを簡単に学習できる優れた情報源はありますか? –

関連する問題