SQL 插入式攻擊是指惡意使用者輸入 Transact-SQL 陳述式,而非提供有效輸入的程序。 如果在未驗證的情況下將輸入直接傳遞至伺服器,而且應用程式不慎執行了以資料隱碼方式撰寫的程式碼,攻擊就可能會破壞或損毀資料。
建構 SQL 陳述式的任何程序都應該經過檢閱,以確認有無插入弱點,因為 SQL Server 會執行收到的所有語法有效查詢。 即使是參數化資料也可能被技術純熟又執意操作的攻擊者操縱。 如果您使用動態 SQL,請務必將命令參數化,且一律不要將參數值直接包含在查詢字串中。
SQL 插入式攻擊的剖析
資料隱碼處理的運作方式是不當地終止文字字串並附加新命令。 因為插入的命令在執行之前可能附加有其他字串,所以不懷好意的人會使用註解標記 "--" 終止插入的字串。 在執行時,後續文字便會被忽略。 可以使用分號 (;) 分隔符號插入多個命令。
只要插入的 SQL 程式碼語法正確,就無法以程式設計方式偵測竄改。 因此,您必須驗證所有使用者輸入,並且仔細檢視在您使用的伺服器中執行建構之 SQL 命令的程式碼。 絕不串連未經驗證的使用者輸入。 字串串連是指令碼資料隱碼的主要進入點。
以下提供一些實用的指導方針:
一律不要直接從使用者輸入建立 Transact-SQL 陳述式,並使用預存程序驗證使用者輸入。
透過測試類型、長度、格式和範圍,驗證使用者輸入。 使用 Transact-SQL QUOTENAME () 函式來逸出系統名稱或 REPLACE () 函式,以逸出字串中的任何字元。
在應用程式的每一層實作多層驗證。
測試輸入的大小和資料類型,並強制執行適當的限制。 這有助於防止蓄意的緩衝區滿溢。
測試字串變數的內容,僅接受預期的值。 拒絕包含二進位資料、逸出序列和註解字元的項目。
使用 XML 文件時,在輸入資料時即驗證所有資料的結構描述。
在多層環境中,所有資料應在進入受信任區域之前進行驗證。
在可用以建構檔案名稱的欄位中,不接受下列字串:AUX、CLOCK$、COM1 到 COM8、CON、CONFIG$、LPT1 到 LPT8、NUL 和 PRN。
搭配預存程序和命令使用 SqlParameter 物件,以提供類型檢查及長度驗證功能。
在用戶端程式碼中使用 Regex 運算式來篩選無效字元。
動態 SQL 策略
在您的程序式程式碼中執行動態建立的 SQL 陳述式會中斷擁有權鏈結,使 SQL Server 針對動態 SQL 所存取的物件檢查呼叫者的權限。
SQL Server 具有一些方法,可使用執行動態 SQL 的預存程序和使用者定義函式來授與資料存取權給使用者。
使用模擬搭配 Transact-SQL EXECUTE AS 子句。
使用憑證簽署預存程序。
EXECUTE AS
EXECUTE AS 子句會將呼叫者的權限取代為 EXECUTE AS 子句中所指定使用者的權限。 巢狀預存程序或觸發程序會以 Proxy 使用者的資訊安全內容執行。 這可能會中斷依賴資料列層級安全性或需要稽核的應用程式。 某些會傳回使用者身分識別的函式會傳回 EXECUTE AS 子句中指定的使用者,而非原始呼叫者。 只有在執行程序之後或發出 REVERT 陳述式時,執行內容才會還原為原始呼叫者。
憑證簽署
當使用憑證簽署的預存程序執行時,授與憑證使用者的權限會與呼叫者的權限合併。 執行內容會維持不變;憑證使用者並不會模擬呼叫者。 簽署預存程序需要實作數個步驟。 每次修改程序之後,都必須重新簽署。
跨資料庫存取
執行以動態方式建立的 SQL 陳述式時,跨資料庫擁有權鏈結無法運作。 您可以在 SQL Server 中建立存取其他資料庫資料的預存程序,並使用存在於兩個資料庫中的憑證來簽署程序,藉此解決上述問題。 這可讓使用者存取由程序所使用的資料庫資源,不需要授與他們資料庫存取權或權限。
外部資源
如需詳細資訊,請參閱下列資源。
| 資源 | 描述 |
|---|---|
| 《SQL Server 線上叢書》中的預存程序和 SQL 資料隱碼 | 各主題會描述如何建立預存程序,以及 SQL 插入式攻擊的運作方式。 |