Mat*_*ete 9 sql-server-2008 sql-injection t-sql
我今天正在查看一个旧的存储过程,并注意到它quotename
在输入参数上使用。在做了一些挖掘以弄清楚它到底做了什么之后,我发现了这个站点。我现在了解它的作用以及如何使用它,但该站点表示它被用作 SQL 注入攻击的缓解措施。当我过去使用 asp.net 开发直接查询数据库的应用程序时,我会使用 ADO.Net 参数将用户输入作为文字值传入,而从不真正担心在我的存储过程中保护它。
我现在正在编写一个存储过程,该过程将由我不编写的应用程序使用,因此我确实需要尝试在过程级别防止注入攻击,这是quotename
最好的方法还是有更新的功能/更好的方法?
让我了解这种思维模式的代码(@parm1
是用户输入参数):
'SELECT project [Project], project_desc [Description],
customer [Customer], cpnyid [Company]
FROM PJPROJ (nolock)
where project like ' + quotename(@parm1,'''') + '
Run Code Online (Sandbox Code Playgroud)
Mar*_*ith 17
是的,这方面的事情没有太大变化,您应该使用quotename
动态 SQL 中使用的任何 SQL 服务器对象名称(特别是如果它们是从外部提供给您的代码)。除了 SQL 注入缓解之外,这也意味着您的代码可以为非标准标识符名称正常工作。
但是,该函数仅适用于对象名称(例如表、列、数据库名称)。
您应该尝试参数化其他所有内容并使用sp_executesql
,传入参数而不是将它们连接到查询字符串中。
关于这个话题的权威文章仍然是The Curse and Blessings of Dynamic SQL
编辑。现在您已经提供了代码,我看到它传递了第二个参数'
以添加外部引号并通过在将它们注入字符串之前将它们加倍来转义任何单引号。这不是quotename 的一个很好的用法。如果字符串大于 128 个字符,它将失败(返回 null)。
此外,如果字符串包含 U+02BC 而不是标准撇号,然后在卫生之后将字符串分配给 varchar(在那里它可以默默地转换为常规撇号),它仍然可能留下 SQL 注入的可能性
正确的方法是让查询参数化。然后将@parm1
值传递给sys.sp_executesql
DECLARE @Sql NVARCHAR(MAX);
SET @Sql = '
SELECT project [Project],
project_desc [Description],
customer [Customer],
cpnyid [Company]
FROM PJPROJ (nolock)
WHERE project LIKE @parm1
';
EXEC sys.sp_executesql
@Sql,
N'@parm1 varchar(100)',
@parm1 = 'foobar%';
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3028 次 |
最近记录: |