SP_EXECUTESQL中的SQL注入

时间:2019-04-17 12:41:04

标签: sql-server tsql sql-injection dynamic-sql

我在SQL Server中有一个存储过程,该存储过程获取XML作为输入参数。在此XML中定义-应该使用哪些存储过程来执行参数值。并且据此,存储过程使用带有sp_executesql的动态SQL执行所需的存储过程。

问题在于参数的值容易受到SQL注入的攻击。<​​/ p>

我尝试过使用像这样的类型化参数:

EXEC sys.sp_executesql 
  @stmt = @sql, 
  @params = N'@Username SYSNAME, @HireDate DATE',
  @UserName = @Username, @HireDate = @HireDate;

但是在我的情况下它实际上不起作用,因为我不知道将执行带有什么参数的程序。参数的数量可能会有所不同,其中一些是可选的/具有默认值等。我所能得到的只是参数名称,如字符串:(

在对输入的XML进行一些解析之后,便像这样构建并执行了SQL查询

declare @params nvarchar(max);
    select @params = coalesce(@params + N', ', N' ') + r.attrName + N' = ' + iif(p.isNumericType = 1, r.Value, '''' + r.Value /*cast(r.Value as nvarchar(max))*/ + '''') --+ r.Value
    from dbo.#ruleConfig r
        left join @spParams p on p.paramName = r.attrName -- datatype of a parameter from information_schema.parameters 

    declare @sql nvarchar(max) = (select @procName + isnull(@params, N''));

    exec dbo.sp_executesql @sql

@sql的值看起来像这样:

'core.GetUser @LogonName = 'myDomain\myLogon''

但是也可以像这样:

'core.GetUser @fullLogonName = 'myDomain\myLogon;'WAITFOR DELAY '0:0:20';--'' and that's the problem.

1 个答案:

答案 0 :(得分:0)

首先,如果您具有任何需要发送 dynamic SQL存储过程执行命令的功能,那么对于每个API来说,对于严格的紧密耦合设计,您的设计都会遇到很大的问题调用将被映射到单个存储过程。

如果您仍然希望坚持使用当前的设计,则必须创建一个已知存储过程及其值的列表。您不能仅仅接受“不知道将执行哪些过程以及带有哪些参数的过程”这一事实,因为您只能按设计发布SQL注入功能。

您需要创建一个已知存储过程的枚举(例如1 = proc1、2 = proc2等),并对其参数执行基于正则表达式的输入验证。

在您刚才给出的示例中,如果希望接受“ myDomain \ myLogon”而拒绝“ myDomain \ myLogon;'WAITFOR DELAY'0:0:20​​';-”,则可以使用正则表达式如下:

RequestTitle

您可以在regexr网站上对其进行测试。 您必须为每种字段类型创建一个输入验证正则表达式-例如名称,用户名,电子邮件等。基本上,这与为每个过程调用创建一个单独的API具有正确的输入验证非常相似。