SQL Server存储过程和SQL注入(inject)

标签 sql sql-server sql-server-2012 sql-injection sql-insert

我使用 SQL Server 2012 并编写一个存储过程。

我想知道我的存储过程中是否存在 SQL 注入(inject)的可能性?

IF OBJECT_ID('Production.InsertProducts', 'P') IS NOT NULL  
  DROP PROCEDURE Production.InsertProducts 
GO 

CREATE PROCEDURE Production.InsertProducts 
  @productname AS NVARCHAR(40)  
  , @supplierid AS INT  
  , @categoryid AS INT  
  , @unitprice AS MONEY = 0 
  , @discontinued AS BIT = 0 
AS 
BEGIN 
    INSERT Production.Products (productname, supplierid, categoryid, unitprice, discontinued) 
    VALUES (@productname, @supplierid, @categoryid, @unitprice, @discontinued); 

    RETURN; 
END; 
GO

或者

IF OBJECT_ID('Production.InsertProducts', 'P') IS NOT NULL  
  DROP PROCEDURE Production.InsertProducts 
GO 

CREATE PROCEDURE Production.InsertProducts 
  @productname AS NVARCHAR(40)  
  , @supplierid AS INT  
  , @categoryid AS INT  
  , @unitprice AS MONEY = 0 
  , @discontinued AS BIT = 0 
AS 
BEGIN 
  Declare @Command NVArchar(Max) = 'INSERT Production.Products (productname, supplierid, categoryid, unitprice, discontinued) 
    VALUES (''' + @productname + ''',' + @supplierid + ',' + @categoryid + ',' + @unitprice + ',' + @discontinued + ');' 
  Execute(@Command);
  RETURN; 
END; 
GO

或者

IF OBJECT_ID('Production.InsertProducts', 'P') IS NOT NULL  
  DROP PROCEDURE Production.InsertProducts 
GO 

CREATE PROCEDURE Production.InsertProducts 
  @productname AS NVARCHAR(40)  
  , @supplierid AS INT  
  , @categoryid AS INT  
  , @unitprice AS MONEY = 0 
  , @discontinued AS BIT = 0 
AS 
BEGIN 
  Declare @Command NVArchar(Max) = '
  INSERT Production.Products (productname, supplierid, categoryid, 
     unitprice, discontinued) 
    VALUES ( @productname , @supplierid,@categoryid,@unitprice,@discontinued);' 

Execute SP_ExecuteSql @Command,
    ' @productname NVARCHAR(40) , @supplierid INT , @categoryid INT  
        , @unitprice  MONEY , @discontinued  BIT ' ,
      @productname= @productname,@supplierid=@supplierid,
        @categoryid=@categoryid,@unitprice=@unitprice,@discontinued=@discontinued
  RETURN; 
END; 
GO

这些查询中哪一个最好?

最佳答案

至于存储过程本身。

第一个没有机会进行 SQL 注入(inject),因为没有动态 SQL。

第三种方法没有 SQL 注入(inject)的机会,因为使用 sp_executesql 编译带有参数的查询,然后插入参数的值。从逻辑上讲,编译发生在参数替换之前,因此参数中的时髦字符串无法改变仅运行单个插入的事实。

第二个很容易受到攻击,因为@productname。其他参数是数字,我认为在字符串中包含数字不会导致漏洞。 (如果我错了,我相信有人会指出这是如何工作的引用。)此类参数存在风险,因为将来有人可能会将它们更改为字符串.

就安全性和最佳实践而言,第一个版本是最安全的。您甚至不必考虑是否存在漏洞。第三个是安全的,但看起来可能不安全。如果您完全担心 SQL 注入(inject),则应避免第二种情况。

至于return的使用,我没有任何问题。它清楚地表明了程序员此时停止执行存储过程的意图。而且,事实上 SQL Server 的 documentation有一个多余的例子。存储过程确实返回值,始终是整数状态代码,我通常使用它们。

关于SQL Server存储过程和SQL注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27219474/

相关文章:

sql - 将 get_absolute_url 组合成 django 中的原始 SQL 语句

php - 快速搜索加密数据?

sql - 我们如何跟踪 SQL Server 中的存储过程更改,就像 TFS 中的版本控制一样

mysql - MySQL 使用 Group By 进行联接时查询性能较差

sql - 客户位置与 hive 中POI之间的距离

sql - 无法从 VS 2012 找到 SQL Server 的 dll

c# - 为什么我的 SqlParameter 没有被识别?

sql-server - TSQL从HTML中删除具有特定src的img标签

sql - 带前缀的 MSSQL 自动递增 ID

sql - 将数据插入 SQL Server 2012