fra*_*lic 9 sql-server validation stored-procedures sql-injection dynamic-sql
我们有大量依赖动态SQL的SQL Server存储过程.
存储过程的参数用于动态SQL语句中.
我们需要在这些存储过程中使用标准验证函数来验证这些参数并防止SQL注入.
假设我们有这些约束:
我们无法重写不使用动态SQL的过程
我们不能使用sp_OACreate等来使用正则表达式进行验证.
在将参数传递给存储过程之前,我们无法修改调用存储过程的应用程序来验证参数.
是否有一组字符我们可以过滤掉以确保我们不会受到SQL注入的影响?
Gab*_*abe 10
我相信你有三种不同的情况需要担心:
'''' + replace(@string, '''', '''''') + ''''quotename(@string)注意:一切在一个字符串变量(char,varchar,nchar,nvarchar即来自用户控制源必须使用上述方法中的一个,等等).这意味着,如果将数字存储在字符串变量中,即使您希望成为数字的内容也会被引用.
有关更多详细信息,请参阅Microsoft Magazine (过时链接:2016-10-19).
以下是使用所有三种方法的示例:
EXEC 'SELECT * FROM Employee WHERE Salary > ''' +
REPLACE(@salary, '''', '''''') + -- replacing quotes even for numeric data
''' ORDER BY ' + QUOTENAME(@sort_col) + ' ' + -- quoting a name
CASE @sort_dir WHEN 'DESC' THEN 'DESC' END -- whitelisting
Run Code Online (Sandbox Code Playgroud)
另请注意,通过在EXEC语句中内联执行所有字符串操作,不会出现截断问题.如果将中间结果分配给变量,则必须确保变量足够大以保存结果.如果这样做,SET @result = QUOTENAME(@name)您应该定义@result至少保留258(2*128 + 2)个字符.如果你这样做,SET @result = REPLACE(@str, '''', '''''')你应该定义@result为大小的两倍@str(假设每个字符@str都可以是引用).当然,保存最终SQL语句的字符串变量必须足够大,以容纳所有静态SQL和所有结果变量.
可以通过QUOTENAME和REPLACE 修复普通案例:
set @sql = N'SELECT ' + QUOTENAME(@column) +
N' FROM Table WHERE Name = ' + REPLACE(@name, '''', '''''');
Run Code Online (Sandbox Code Playgroud)
虽然QUOTENAME也可用于文字,但是添加单引号并用双引号替换单引号,因为它将输入截断为128个字符,因此不推荐使用.
但这只是冰山一角.dbo.table您需要妥善处理多部分名称():引用多部分名称会导致标识符无效[dbo.table],必须对其进行解析和拆分(使用PARSENAME),然后正确引用[dbo].[table].
另一个问题是截断攻击,即使您对文字进行了简单的REPLACE,也会发生这种情况,请参阅新SQL截断攻击以及如何避免它们.
SQL注入的问题永远不能通过在每个过程上放置一个魔术函数来解决.这就像问'我想要一个能让我的代码运行得更快的功能'.防止注入攻击是端到端游戏,需要编码规则一直通过,它不能简单地添加为事后的想法.您最好的机会是检查每个程序并逐行分析T-SQL代码,并密切关注漏洞,然后在发现问题时解决问题.
| 归档时间: |
|
| 查看次数: |
12209 次 |
| 最近记录: |