如何使用sp_executesql避免SQL注入

如何使用sp_executesql避免SQL注入

问题描述:

在下面的示例代码中,表名是输入参数。在这种情况下,我如何避免使用sp_executesql进行SQL注入。下面是示例代码,我试图使用sp_executesql来避免它,但它不起作用。任何人都可以告诉我如何改正它?如何使用sp_executesql避免SQL注入

ALTER PROC Test @param1 NVARCHAR(50), 
       @param2 INT, 
       @tblname NVARCHAR(100) 
AS 
    BEGIN 
     DECLARE @sql NVARCHAR(1000) 

     SET @sql= N' select * from ' + @tblname 
       + ' where name= @param1 and id= @param2'; 

     PRINT @sql 

     EXEC Sp_executesql 
     @sql, 
     N'@param1 nvarchar(50), @param2 int', 
     @param1, 
     @param2; 
    END 

EXEC Test 
    'John', 
    2, 
    ' emp; delete from emp where id = 567; select * from emp ' 

输出: 打印消息:

select * from emp; delete from emp where id = 567; select * from emp where name= @param1 and id= @param2; 

所有的输入参数是否完全取代和一个行被删除。 请让我知道如何处理这种情况。

+0

尝试在'[]' – 2015-03-25 03:28:57

+1

中附上表格谢谢,它工作:) – Suj 2015-03-25 03:31:22

+0

仍然脆弱:'emp];从emp中删除id = 567;选择* from [emp' – Gumbo 2015-03-25 05:22:10

可以在[]

SET @sql= N' select * from [' + @tblname + '] where name= @param1 and id= @param2'; 

封闭表名但是,如果使用两部分命名约定如dbo.tablename,你必须添加额外的解析,因为[dbo.tablename]将导致到:

无效的对象名称[dbo.tablename]。

您应该解析它,以便它等于dbo.[tablename]

你可以首先检查参数值的确是一个表名:

ALTER PROC Test @param1 NVARCHAR(50), 
      @param2 INT, 
      @tblname NVARCHAR(100) 
AS 
BEGIN 
    DECLARE @sql NVARCHAR(1000) 

    IF EXISTS(SELECT 1 FROM sys.objects WHERE type = 'u' AND name = @tblname) 
    BEGIN 
     SET @sql= N' select * from ' + @tblname 
       + ' where name= @param1 and id= @param2'; 

     PRINT @sql 

     EXEC Sp_executesql 
     @sql, 
     N'@param1 nvarchar(50), @param2 int', 
     @param1, 
     @param2; 
    END 
END 

如果传递的值不是表命名您的程序不会做任何事情;或者你可以改变它来抛出一个错误。如果参数包含查询,这样你就很安全。

+0

谢谢乔希:) – Suj 2015-03-25 21:53:57