最近在處理StoreProcedure撰寫動態語法SQL Injection的問題,整理後記錄下來,SQL Server主要是使用 sp_executesql 來處理,MySQL是使用 PREPARE 搭配 EXECUTE 來執行。
最近在處理StoreProcedure撰寫動態語法SQL Injection的問題,整理後記錄如下。
在此針對SQL Server及MySQL的處理方式做說明。
先以SQL Server示範一個錯誤的例子(以北風資料庫為例)。
一、動態SQL錯誤(不安全)範例(MSSQL):
USE Northwind;
-- 宣告變數
DECLARE @strSQL NVarchar(100);
DECLARE @ContactTitle NVarchar(30);
DECLARE @City NVarchar(15);
-- 設定條件值
SET @ContactTitle = N'Sales Representative';
SET @City = N'London';
-- 動態組出SQL陳述式
SET @strSQL = N'SELECT * FROM Customers WHERE ContactTitle = ''' + @ContactTitle
+ ''' AND City = ''' + @City + '''';
-- 執行
exec (@strSQL)
以上方式因為是將條件值以組字串的方式執行,會有SQL Injection的問題,非常容易遭到駭客攻擊!
正確的寫法應使用 sp_executesql 來處理。
二、動態SQL正確範例:
USE Northwind;
-- 宣告變數
DECLARE @strSQL NVarchar(100);
DECLARE @ContactTitle NVarchar(30);
DECLARE @City NVarchar(15);
DECLARE @ParmDefinition NVarchar(500);
-- 設定條件值
SET @ContactTitle = N'Sales Representative';
SET @City = N'London';
-- 動態組出SQL陳述式(SQL語法跟 .NET組動態SQL寫法一樣)
SET @strSQL = N'SELECT * FROM Customers WHERE ContactTitle = @ContactTitle AND City = @City';
-- 定義傳入的參數型態 (與strSQL中的變數名稱對應)
SET @ParmDefinition = N'@ContactTitle NVarchar(30), @City NVarchar(15)';
-- 透過sp_executesql執行
exec sp_executesql @strSQL, @ParmDefinition , @ContactTitle, @City;
sp_executesql參數說明如下:
第1個參數:傳入要執行的SQL陳述式。
第2個參數:定義SQL陳述式中的參數型態。
第3個參數:要傳入的參數值,多個參數以半型號分隔。
StoreProcedure使用此方式撰寫時,需注意權限的設定,當使用exec直接執行SQL陳述式時,只要設定StoreProcedure的執行權限即可,但若透過sp_executesql執行,除了須設定StoreProcedure的執行權限外,也要設定Table相對應的使用權限才可正常執行,以上述程式碼為例,是進行select的動作,所以也要開啟可對Customers資料表做select的權限才可正常執行。
三、MySQL動態SQL範例:
在MySQL中,從5.0版本開始支援動態語法,使用 PREPARE 搭配 EXECUTE 執行。
-- 動態組出SQL陳述式(參數是使用問號(?)帶入)
SET @strSQL ='SELECT * FROM Customers WHERE ContactTitle = ?';
SET @strSQL = concat(@strSQL, ' AND City = ?');
-- 設定條件值
SET @ContactTitle = 'Sales Representative'; SET @City = 'London';
-- 執行
PREPARE preSQL FROM @strSQL;
EXECUTE preSQL USING @ContactTitle, @City;
preSQL是我們自己定義的名稱,USING傳入的變數是要帶入的參數,順序須與語法中問號(?)出現的順序相同。
MySQL還有一個釋放資源DEALLOCATE PREPARE的用法,在此例中未使用,當資料庫連線關閉時伺服器會自動釋放。
參考連結:
SQL Server:
MySQL:
延伸閱讀:
- 在SQL Server中使用sp_executesql如何指定輸出參數
- SQL Injection (資料隱碼)– 駭客的 SQL填空遊戲
- LINQ - 對付 SQL Injection 的 "免費補洞策略"
2010/3/17:看到網友 hunterpo 的動態SQL文章,將文章連結加註在此,方便以後參考 (謝謝 hunterpo 分享)