2009-04-01 14 views
7

サニタイジング、ちょうど私がINSERTを持つSQLクエリを含むローカル変数を作成に持ってとしましょう:SQL Serverの:引数のためにインジェクション攻撃に対する@param

DECLARE @insert NVARCHAR(MAX) 
SELECT @insert = 'INSERT INTO [dbo].[' + @table + '] VALUES... 
EXEC (@insert) 

これINSERTでもあります列の値含めるしよう:今すぐ

DECLARE @insert NVARCHAR(MAX) 
SELECT @insert = 
    'INSERT INTO [dbo].[' + @table + '] VALUES (N''' + @message + ''')' 
EXEC (@insert) 

を、私は明らかにインジェクション攻撃を懸念だし、その@メッセージの値は、@挿入の値が悪意のあるまたはEXECへのクエリとして不正な形式にすることはできませんことを確認したいと思います。

これは私の質問に私をもたらします。「メッセージの文字を十分にエスケープしていますか? @messageに出てくる可能性のある他の文字がありますか?

例:

DECLARE @insert NVARCHAR(MAX) 
SELECT @message = REPLACE(@message,'''','''''') 
SELECT @insert = 
    'INSERT INTO [dbo].[' + @table + '] VALUES (N''' + @message + ''')' 
EXEC (@insert) 

(私は「に持っている」と言うとき、INSERT先のテーブルである、私のクエリは、ストアドプロシージャであるため、これは、このストアドプロシージャが@table受け入れます私は自分のアーキテクチャについて議論することに興味がありませんし、INSERTするテーブルがプロシージャのパラメータで「動的に」指定されているのはなぜですか?EXEC()以外の方法でテーブルを指定する方法プロシージャパラメータとしてテーブル名が受け取られたときにINSERTします。

+1

意図的に悪いコードを書く方法を扱う質問に本当に対処したいですか? – dkretz

+7

解決策を見つけることを意味する場合、はい。開発者は、バングラデシュで書かれたプロジェクトをコンサルティングして8ドル/時間で継承している場合は、常に虚偽のコードを扱わなければなりません。私たちは常に、プロジェクトを最初から構築し、それを構築するべき方法を構築するという贅沢を得ているわけではありません。:) – core

答えて

10

sp_executesqlと組み込みのquotename()を使用してください。この記事、The Curse and Blessings of Dynamic SQLは、かなり参考になります。

+0

++ canonical reference – dkretz

+0

2008年にもquotename()に128文字の制限がありますが、これはSQL識別子が必要なためです。この参照は、REPLACEと全く同じことを行うquotestring()関数(http://www.sommarskog.se/dynamic_sql.html#quotestring)を作成することを示唆しています(@variable、 '' '、' '' '' ' )。 – core

1

EXEC(@somesql)を呼び出すのではなく、sp_executesql stored procedureを使用することをお勧めします。具体的には、これによりパラメータを渡すことができ、システムはパラメータが有効であることをチェックします。

+0

残念ながら、SQL Server 2008 Expressは「テーブル変数 '@my_table'を宣言しなければなりません」と伝えています。そのコードを実行した後 – core

+0

私はSQL Server 2005でこれをやったと確信していましたが、私は非常に疲れていると認めます。謝罪します。私は明日これを試してみるよ。 –

+0

いいえ、私は間違っています。私は答えのその部分を削除します。 –

1

まず、正規のT-SQLでスキーマ情報を照会し、最初にテーブル名が存在することを確認します。このようにして、不正な形式のSQLの場合、コードとして実行されません。これはVARCHAR表名になります。

DECLARE @Table AS VARCHAR(MAX) 
DECLARE @Exists AS BIT 

SET @Table = 'Vicious malformed dynamic SQL' 

SELECT @Exists = COUNT(TABLE_NAME) 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_NAME = @Table 

IF (@Exists = 1) 
    BEGIN 
    PRINT 'Table exists' 
    -- Execute dynamic SQL. 
    END 
ELSE 
    PRINT 'Invalid table' 

それはSQLを期待するので、私のテストによるとさえ2008年には、

+0

良い考え。私は次のことをしてきました。どちらの利点もありますか?私がやっていること: "IF OBJECT_ID(@ table、 'U')IS NULL ..." – core

0

はどうやら(QUOTENAMEする128の長さの制限があります)(または単にIFは、(SELECT ...)EXISTSを使用)識別子。

CREATE FUNCTION quotestring(@string nvarchar(MAX)) 
RETURNS nvarchar(MAX) AS 
BEGIN 
    RETURN(REPLACE(@string,'''','''''')) 
END 
:したがって、私はそうのように、上記の)答えは(REPLACEの外に関数を作成することであることを提案しています

REPLACE(@variable,'''','''''') 

:参照は、同じことをやっquotestring()機能を、作成示唆します

...私が何か誤解していない限り。

+0

そのようなパラメータとしてnvarchar(MAX)を渡すことはできますか? –

+0

もちろん、どうしてですか?これは私の開発者の操作機能です。環境。 :) – core

関連する問題