How to use sp_executesql to avoid SQL Injection

无人久伴 提交于 2019-12-31 03:41:46

问题


In the below sample code, Table Name is an input parameter. In this case, how can I avoid SQL injection using sp_executesql. Below is the sample code, I am trying to use sp_executesqlto avoid it but it doesn't work. Can anyone tell me how to correct it?

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 ' 

Output: Print message:

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

All the input parameters are exactly substituted and one row is deleted. Please let me know how to handle this scenario.


回答1:


You can enclose the table name in []

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

However, if you use a two-part naming convention e.g dbo.tablename, you have to add additional parsing, since [dbo.tablename] will result to:

Invalid object name [dbo.tablename].

You should parse it so that it'll be equal to dbo.[tablename].




回答2:


You could first check if the parameter value is indeed a table name:

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 

If the passed value is not a table name your procedure won't do anything; or you could change it to throw an error. This way you're safe if the parameter contains a query.



来源:https://stackoverflow.com/questions/29246897/how-to-use-sp-executesql-to-avoid-sql-injection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!