我们是否仍应使用QUOTENAME防止注入攻击?


9

我今天正在看一个旧的存储过程,发现它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,'''') + '

Answers:


17

是的,在这方面变化不大,您应该使用quotename动态SQL中使用的任何SQL Server对象名称(尤其是在外部提供给您的代码的情况下)。除了减轻SQL注入外,这还意味着您的代码对于非标准标识符名称也可以正常工作。

但是,该功能仅适用于对象名称(例如,表,列,数据库名称)。

您应该尝试对其他所有参数进行参数化,然后使用sp_executesql传递参数,而不要将其串联到查询字符串中。

关于该主题的权威文章仍然是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%'; 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.