我们有大量依赖动态 SQL 的 SQL Server 存储过程。
存储过程的参数在动态 SQL 语句中使用。
我们需要在这些存储过程中使用标准验证函数来验证这些参数并防止 SQL 注入。
假设我们有这些约束:
我们无法重写过程以不使用动态 SQL
我们不能使用 sp_OACreate 等来使用正则表达式进行验证。
我们无法修改调用存储过程以在参数传递到存储过程之前验证参数的应用程序。
是否有一组字符可以过滤掉以确保我们不会受到 SQL 注入的影响?
我相信您需要担心三种不同的情况:
- 字符串(任何需要引号的内容):
'''' + replace(@string, '''', '''''') + ''''
- 名称(不允许使用引号的任何名称):
quotename(@string)
- 不能引用的东西:这需要白名单
Note: 一切在字符串变量中(char
, varchar
, nchar
, nvarchar
等)来自用户控制的源必须使用上述方法之一。这意味着,即使您希望是数字的东西,如果存储在字符串变量中,也会被引用。
For more details, see the Microsoft Magazine http://msdn.microsoft.com/en-us/magazine/cc163523.aspx (Obsolete link: 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
另请注意,通过在EXEC
声明不存在截断问题。如果将中间结果分配给变量,则must确保变量足够大以保存结果。如果你这样做SET @result = QUOTENAME(@name)
你应该定义@result
至少包含 258 (2 * 128 + 2) 个字符。如果你这样做SET @result = REPLACE(@str, '''', '''''')
你应该定义@result
是两倍大小@str
(假设中的每个字符@str
可以是一个报价)。当然,保存最终 SQL 语句的字符串变量必须足够大,以容纳所有静态 SQL 以及所有结果变量。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)