インジェクション攻撃から保護するためにQUOTENAMEを引き続き使用する必要がありますか?


9

今日、古いストアドプロシージャを見ていquotenameて、入力パラメーターで使用されていることに気付きました。それが何をしているのかを正確に理解するために少し掘り下げた後、私はこのサイトを見つけました。私はそれが何をするか、そしてそれをどのように使うかを理解しました、しかしサイトはそれがSQLインジェクション攻撃からの緩和として使われると言います。asp.netを使用してデータベースを直接クエリするアプリを開発していたときは、ADO.Netパラメータを使用してユーザー入力をリテラル値として渡し、ストアドプロシージャでそれを保護することについて心配することはありませんでした。

現在、自分が記述し​​ていないアプリケーションで使用されるストアドプロシージャを記述しているので、プロシージャレベルでインジェクション攻撃から保護する必要quotenameがあります。これは、これを行うための最良の方法であるか、より新しい機能/優れた方法があります。方法?

この思考パターンに私を導いたコード(@parm1ユーザー入力パラメーターです):

'SELECT project [Project], project_desc [Description], 
        customer [Customer], cpnyid [Company]
FROM PJPROJ (nolock)
where project like ' + quotename(@parm1,'''') + '

回答:


17

はい、この領域ではほとんど変更されていません。quotename動的SQLで使用されるSQLサーバーオブジェクト名に使用する必要があります(特に、コードの外部で提供される場合)。SQLインジェクションの緩和だけでなく、これはコードが非標準の識別子名でも正しく機能することを意味します。

ただし、この関数はオブジェクト名(テーブル、列、データベース名など)にのみ適しています。

他のすべてをパラメータ化して使用sp_executesqlし、クエリ文字列に連結するのではなく、パラメータを渡して使用する必要があります。

このトピックに関する最も信頼できる記事は、まだ動的SQLの呪いと祝福です。


編集。これで、2番目のパラメーターを渡し'て外側の引用符を追加し、文字列に挿入する前に二重引用符で二重引用符をエスケープするためにエスケープするコードを指定しました。これはquotenameの良い使い方ではありません。文字列が128文字を超えると失敗します(nullを返します)。

さらに、文字列に標準のアポストロフィの代わりにU + 02BCが含まれている場合、SQLインジェクションの可能性が残っている可能性があります。その後、文字列は、サニテーションの後にvarcharに割り当てられます(通常のアポストロフィに静かに変換されます)。

これを行う正しい方法は、クエリをパラメーター化したままにすることです。そして、@parm1値をに渡しますsys.sp_executesql

DECLARE @Sql NVARCHAR(MAX);

SET @Sql = '
SELECT project      [Project],
       project_desc [Description],
       customer     [Customer],
       cpnyid       [Company]
FROM   PJPROJ (nolock)
WHERE  project LIKE @parm1 
';

EXEC sys.sp_executesql
  @Sql,
  N'@parm1 varchar(100)',
  @parm1 = 'foobar%'; 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.