提问人:Patricie Benesova 提问时间:4/17/2019 最后编辑:marc_sPatricie Benesova 更新时间:4/25/2019 访问量:798
SP_EXECUTESQL中的 SQL 注入
SQL injection in SP_EXECUTESQL
问:
我在SQL Server中有一个存储过程,它获取XML作为输入参数。在此XML中定义了 - 应该使用哪些参数值执行哪些存储过程。并据此,存储过程使用动态 SQL 执行所需的 .sp_executesql
问题在于参数的值容易受到 SQL 注入的影响。
我尝试过使用这样的类型化参数:
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.
答:
首先,如果有任何功能需要发送动态 SQL 存储过程执行命令,则您的设计存在一个大问题,因为使用严格的紧密耦合设计时,每个 API 调用都将映射到单个存储过程。
如果您仍然希望坚持使用当前设计,则必须创建已知存储过程及其值的列表。你不能只是接受这样一个事实,即你“不知道将执行什么过程和什么参数”,因为你发布SQL注入功能是按设计设计的。
您需要创建已知存储过程(例如 1 = proc1、2 = proc2 等)的枚举,并对其参数执行基于正则表达式的输入验证。
在刚才给出的示例中,如果您希望接受“myDomain\myLogon”和“myDomain\myLogon;”WAITFOR DELAY '0:0:20';--“ 被拒绝,例如,您可以使用如下所示的正则表达式:
^([A-Za-z\\])*$
您可以在 regexr 网站上对其进行测试。 您必须为每个字段类型创建一个输入验证正则表达式 - 例如名称、用户名、电子邮件等。基本上,这与为每个过程调用创建一个单独的 API 非常相似,并具有适当的输入验证。
评论
In this XML is defined - what store procedure with which parameters values should be executed.
为什么?为什么让数据库分析此字符串,而不是让客户端正确调用存储过程?这是问题的根源,而不是sp_executesql
EXEC sp_executesql N'SELECT 1 AS one;',N'@i int', @i = @i;
@i