为了论证,我们只是说我必须创建一个包含具有INSERT的SQL查询的局部变量:
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)
现在,我显然关注注入攻击,并希望确保@ message的值不会使@ insert的值恶意或格式错误,作为对EXEC的查询。
这给我们带来了一个问题:逃避@message中的'字符是否足够? @message中是否还有其他字符可以逃脱?
示例:
DECLARE @insert NVARCHAR(MAX)
SELECT @message = REPLACE(@message,'''','''''')
SELECT @insert =
'INSERT INTO [dbo].[' + @table + '] VALUES (N''' + @message + ''')'
EXEC (@insert)
(当我说“必须”时,这是因为我的查询是在存储过程中,并且此存储过程接受@table,这是要插入的目标表。我是没有兴趣讨论我的体系结构或者为什么要通过过程参数“动态”指定要插入的表。请不要评论此,除非EXEC()除了EXEC()查询指定要插入INSERT的表之外的其他方法何时接收表名作为过程参数。)
答案 0 :(得分:10)
使用sp_executesql
和内置quotename()
。这篇文章The Curse and Blessings of Dynamic SQL几乎是最权威的参考。
答案 1 :(得分:1)
我建议使用sp_executesql stored procedure,而不是调用EXEC(@somesql)。具体来说,这允许您传递参数,系统将检查参数是否有效。
答案 2 :(得分: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'
(或者只是使用IF EXISTS(SELECT ....))
答案 3 :(得分:0)
显然,对于quotename()有128个长度限制,即使在2008年根据我的测试,因为它需要一个SQL标识符。该参考文献建议创建一个quotestring()函数,其功能与:
相同REPLACE(@variable,'''','''''')
因此我建议答案是从上面的REPLACE()创建一个函数,如下所示:
CREATE FUNCTION quotestring(@string nvarchar(MAX))
RETURNS nvarchar(MAX) AS
BEGIN
RETURN(REPLACE(@string,'''',''''''))
END
......除非我误解了什么。
答案 4 :(得分:0)
在编写动态SQL时,您将需要尽可能地参数化,并且在绝对必要时仅求助于字符转义。您无法参数化@table,但是可以参数化@message。
DECLARE @insert NVARCHAR(MAX)
set @insert = 'INSERT INTO [dbo].' + quotename(@table) + ' values(@message)'
exec sys.sp_executesql @insert, N'@message nvarchar(max)', @message = @inMessage;
攻击者可以通过多种方式利用动态SQL,包括缓冲区长度攻击和使用Unicode等效字符。我曾经遇到一个示例,其中转义单引号char仍然存在一个漏洞,可以传递该引号char的unicode等效项之一。部分软件堆栈正在执行unicode到ascii的转换,因此可以注入a他们逃脱后再次引用。哎呀。