SQL Server:针对注入攻击消除@param

时间:2009-04-01 02:35:33

标签: sql sql-server sql-injection

为了论证,我们只是说我必须创建一个包含具有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的表之外的其他方法何时接收表名作为过程参数。)

5 个答案:

答案 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他们逃脱后再次引用。哎呀。

相关问题