2015-03-25 190 views
1

在下面的示例代碼中,表名是輸入參數。在這種情況下,我如何避免使用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

回答

0

可以在[]

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

封閉表名但是,如果使用兩部分命名約定如dbo.tablename,你必須添加額外的解析,因爲[dbo.tablename]將導致到:

無效的對象名稱[dbo.tablename]。

您應該解析它,以便它等於dbo.[tablename]

1

你可以首先檢查參數值的確是一個表名:

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