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

ASP 防 SQL 注入輸入過濾函數:SafeRequest 進化版與現代替代方案

     編輯:關於SqlServer

背景與局限性說明

原文提供的 SafeRequest 函數採用黑名單關鍵字過濾 (select, insert, xp_cmdshell 等),屬於「補丁式防禦」,存在根本缺陷:

  • ❌ 繞過簡單:大小寫變形、編碼 (%53%45%4C%45%43%54)、註解插入 (SEL/**/ECT)、字串拼接 (EXEC('SEL'+'ECT')) 皆可繞過。
  • ❌ 误攔截:正常業務欄位含「select」「update」「delete」等單字 (如「selection」「update_time」) 會被誤判。
  • ❌ 維護地獄:新攻擊向量層出不窮,黑名單永遠追不上。
  • ❌ 偽安全感:管理者以為加了此函數就安全,忽略真正根治方案。
結論:黑名單過濾不能作為主要防禦手段,僅可作為「臨時虛擬補丁」在無法修改程式碼的舊系統上緩解風險,並需嚴格記錄、追蹤、計劃替換。

現代根治方案:參數化查詢 (唯一正解)

ASP + ADO 經典寫法修正

' ❌ 危險:字串拼接
sql = "SELECT * FROM News WHERE Id = " & Request("id")
Set rs = conn.Execute(sql)

' ✅ 安全:參數化命令
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = "SELECT * FROM News WHERE Id = ?"
cmd.CommandType = 1 ' adCmdText
cmd.Parameters.Append cmd.CreateParameter("Id", 3, 1, , Request("id")) ' adInteger=3
Set rs = cmd.Execute()

ASP.NET (Web Forms / MVC) 範例

// ❌ 危險
string sql = "SELECT * FROM News WHERE Id = " + Request.QueryString["id"];

// ✅ 安全:SqlParameter
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM News WHERE Id = @Id", conn)) {
    cmd.Parameters.Add("@Id", SqlDbType.Int).Value = Convert.ToInt32(Request.QueryString["id"]);
    conn.Open();
    using (SqlDataReader dr = cmd.ExecuteReader()) { ... }
}

存儲過程 + 參數化 (雙重保險)

CREATE PROC usp_GetNews @Id INT
AS
SELECT * FROM News WHERE Id = @Id;
GO

-- 呼叫端
cmd.CommandText = "usp_GetNews";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@Id", id);

若必須使用過濾函數 (舊系統無法重構),改良版 SafeRequest

Function SafeRequest(ByVal ParaName)
    Dim ParaValue, CleanValue
    ParaValue = Request(ParaName)
    
    ' 1. 純數字直接通過 (常見 ID、頁碼)
    If IsNumeric(ParaValue) Then
        SafeRequest = ParaValue
        Exit Function
    End If
    
    ' 2. 基礎清理:單引號雙寫 (防基本注入)、移除註解標記
    CleanValue = Replace(ParaValue, "'", "''")
    CleanValue = Replace(CleanValue, "--", "")
    CleanValue = Replace(CleanValue, ";", "")
    
    ' 3. 白名單驗證 (按業務欄位定義允許字元集)
    ' 範例:僅允許中英數字、底線、連字號、空格
    Dim regEx, matches
    Set regEx = New RegExp
    regEx.Pattern = "^[\w\u4e00-\u9fa5\s\-]+$"  ' 需 VBScript 5.5+ 支援 Unicode
    regEx.Global = True
    regEx.IgnoreCase = True
    
    If regEx.Test(CleanValue) Then
        SafeRequest = CleanValue
    Else
        ' 記錄攻擊嘗試 (寫入資料庫/事件日誌/檔案)
        Call LogAttackAttempt(ParaName, ParaValue, Request.ServerVariables("REMOTE_ADDR"))
        
        ' 友善阻擋 (不洩露技術細節)
        Response.Write ""
        Response.End
    End If
End Function

纵深防御補充措施

層面措施工具/配置
資料庫最小權限帳號、移除 xp_cmdshell、啟用稽核sp_dropextendedproc, C2 稽核
網路WAF 規則集 (OWASP CRS)、IP 信譽封鎖ModSecurity, Azure WAF, Cloudflare
主機錯誤訊息不回顯、自訂錯誤頁面、詳細日誌落本地web.config , Elmah
開發流程靜態掃描 (SonarQube)、Code Review 清單、安全編碼培訓規則: S2077, S3649, S5147
運行時RASP 監控異常 SQL 模式、資料庫活動監控 (DAM)Imperva, Guardium, 開源 DBShield

結語

SQL 注入的根因是「資料與代碼未分離」。參數化查詢 從語法層面徹底切斷攻擊路徑,是唯一正確、標準、可維護的解法。黑名單過濾函數只能作為遷移期間的臨時緩解,決不可長期依賴。建立「安全左移」文化:需求階段威脅建模、編碼階段參數化規範、測試階段自動掃描、上線後持續監控,才能從根本消除注入風險。

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