如何使用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;
所有的输入参数是否完全取代和一个行被删除。 请让我知道如何处理这种情况。
答
可以在[]
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
尝试在'[]' – 2015-03-25 03:28:57
中附上表格谢谢,它工作:) – Suj 2015-03-25 03:31:22
仍然脆弱:'emp];从emp中删除id = 567;选择* from [emp' – Gumbo 2015-03-25 05:22:10