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

通用分頁預存程序真的有 SQL 注入漏洞嗎?深度剖析與防範

     編輯:關於SqlServer

近期社群討論「高效通用分頁預存程序帶有 SQL 注入漏洞」及「防注入:參數化通用分頁查詢」。筆者認為:預存程序本身不存在注入漏洞,漏洞源於應用層拼接 SQL 字串時未妥善處理參數。若有實際注入手法,請不吝指教。

簡化場景重現

建立 person 表(id、last_name、first_name),撰寫查詢預存程序 getPerson 接收 @strWhere 參數動態拼接:

CREATE PROC getPerson
    @strWhere VARCHAR(100) = '' -- 查詢條件(勿含 WHERE 關鍵字)
AS
BEGIN
    DECLARE @strSQL VARCHAR(1000);
    SET @strSQL = 'SELECT TOP 10 * FROM person WHERE 1=1 ';
    IF @strWhere != ''
        SET @strSQL = @strSQL + @strWhere;
    PRINT(@strSQL);
    EXEC(@strSQL);
END

注入風險點

若應用層直接拼接使用者輸入:

-- 不安全寫法
strWhere += " AND first_name LIKE '%" + sUserName + "%'";

當 sUserName = "Jim's dog" 時,單引號閉合導致語法錯誤或被惡意利用。正確格式應為 AND first_name LIKE '%Jim''s dog%'(單引號轉義為雙引號)。

應用層防禦範例

public string SafeRequest(string str) {
    str = str.ToLower();
    string SQL_KILL = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|set|;|from|=|--|drop|<|>";
    foreach (string kw in SQL_KILL.Split('|')) {
        if (str.IndexOf(kw) > -1) {
            if (kw == "'") str = str.Replace("'", "''");
            else str = str.Replace(kw, "");
        }
    }
    return str;
}

// 使用
if (!string.IsNullOrEmpty(sUserName))
    strWhere += " AND first_name LIKE '%" + SafeRequest(sUserName) + "%'";

另需注意十六進位編碼繞過過濾,建議同步檢查 HTML 編碼後的敏感字元。

為何不推薦「通用分頁預存程序」

  1. 可讀性極差,全是字串拼接,維護困難
  2. 對應用層安全要求高,稍疏忽即留漏洞
  3. 複雜多表查詢無力支援,強行套用反增複雜度
  4. 結構公開,增加被攻擊面

防範拼接 SQL 風險的五大原則

  1. 參數強型別:能用數值型絕不用字串型
  2. 限制參數長度:如姓名不超過 20 字元
  3. 輸入修剪:Trim() 移除前後空格,破壞潛在注入語法
  4. 過濾敏感字元:至少將單引號轉義為雙引號
  5. 最小權限原則:查詢帳號唯讀、寫入帳號禁 DROP/TRUNCATE,注入成功亦難造成毀滅性後果

結論:通用分頁預存程序本身無漏洞,漏洞源於應用層拼接不嚴謹。建議採用參數化查詢或 ORM 框架,從根源杜絕注入風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved