首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 自訂純量函數防 SQL 注入:字串清洗實作與預存程序整合範例

     編輯:關於SqlServer

清洗函數 `dbo.fn_SanitizeInput`

CREATE FUNCTION dbo.fn_SanitizeInput (@input NVARCHAR(4000))
RETURNS NVARCHAR(4000)
AS
BEGIN
    -- 移除常見 SQL 注入特徵字元
    SET @input = REPLACE(@input, N'''', N'');      -- 單引號
    SET @input = REPLACE(@input, N'"', N'');       -- 雙引號
    SET @input = REPLACE(@input, N':', N'');       -- 冒號 (ODBC 逸出)
    SET @input = REPLACE(@input, N'-', N'');       -- 註解起始 --
    SET @input = REPLACE(@input, N';', N'');       -- 批次分隔符 (防堆疊注入)
    SET @input = REPLACE(@input, N'/*', N'');      -- 註解開始
    SET @input = REPLACE(@input, N'*/', N'');      -- 註解結束
    SET @input = REPLACE(@input, N'xp_', N'');     -- 擴充預存程序前綴
    SET @input = REPLACE(@input, N'sp_', N'');     -- 系統預存程序前綴
    RETURN @input;
END
GO
注意:黑名單過濾**非絕對安全**,繞過手法層出不窮 (Unicode 同形字、編碼、截斷等)。**根本防禦請見下文**。

預存程序整合範例:登入驗證

CREATE PROCEDURE dbo.usp_ValidateLogin
    @username NVARCHAR(50),
    @password NVARCHAR(50),
    @result   INT OUTPUT  -- 0=成功, -1=帳號不存在, -2=密碼錯誤, -3=鎖定
AS
BEGIN
    SET NOCOUNT ON;

    -- 1. 輸入清洗 (防禦深度:即使參數化仍清洗,防二次注入/日誌污染)
    SET @username = dbo.fn_SanitizeInput(@username);
    SET @password = dbo.fn_SanitizeInput(@password);

    -- 2. 參數化查詢 (核心防線:查詢計畫與資料分離)
    DECLARE @stored_hash NVARCHAR(128), @status TINYINT;
    SELECT @stored_hash = PasswordHash, @status = AccountStatus
    FROM dbo.Users
    WHERE Username = @username;  -- 參數化,無注入風險

    IF @@ROWCOUNT = 0
    BEGIN
        SET @result = -1; RETURN;  -- 帳號不存在
    END

    IF @status = 1  -- 鎖定狀態
    BEGIN
        SET @result = -3; RETURN;
    END

    -- 3. 密碼驗證 (此處簡化為明文比對,實務必用 BCrypt/Argon2/PBKDF2 驗證雜湊)
    IF @stored_hash = @password  -- 實務:IF dbo.fn_VerifyHash(@password, @stored_hash) = 1
    BEGIN
        SET @result = 0;  -- 成功
    END
    ELSE
    BEGIN
        SET @result = -2;  -- 密碼錯誤
        -- 可加入失敗計數、達閾值鎖定邏輯
    END
END
GO

根本防禦三大支柱 (清洗函數只是輔助)

  1. 參數化查詢 / 預存程序參數:所有動態值**絕不**字串拼接進 SQL。`sp_executesql` + 參數、`SqlCommand.Parameters.Add`、ORM 參數化。
  2. 最小權限帳號:應用連線帳號**僅擁有**必要物件的 `SELECT/INSERT/UPDATE/DELETE/EXECUTE` 權限,**無** `sysadmin`、`db_owner`、`ddl_admin`、`xp_cmdshell` 權限。
  3. 輸入驗證 (白名單):應用層依業務規則驗證 (長度、格式、範圍、字元集),**拒絕**不符合預期的輸入,而非試圖過濾壞字元。

補充:動態 SQL 安全模板

CREATE PROCEDURE dbo.usp_SearchUsers
    @searchTerm NVARCHAR(100),
    @role       NVARCHAR(20) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @sql NVARCHAR(MAX), @params NVARCHAR(MAX);

    SET @sql = N'SELECT UserID, Username, Email FROM dbo.Users WHERE 1=1';
    SET @params = N'@term NVARCHAR(100), @role NVARCHAR(20)';

    IF @searchTerm IS NOT NULL
        SET @sql += N' AND (Username LIKE @term OR Email LIKE @term)';
    IF @role IS NOT NULL
        SET @sql += N' AND Role = @role';

    EXEC sp_executesql @sql, @params,
        @term = N'%' + @searchTerm + N'%',  -- 參數化,安全
        @role = @role;
END
動態 SQL **必須**使用 `sp_executesql` + 參數化,**禁止**在 `@sql` 字串中直接拼接變數值。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved