原文提供的 SafeRequest 函數採用黑名單關鍵字過濾 (select, insert, xp_cmdshell 等),屬於「補丁式防禦」,存在根本缺陷:
%53%45%4C%45%43%54)、註解插入 (SEL/**/ECT)、字串拼接 (EXEC('SEL'+'ECT')) 皆可繞過。結論:黑名單過濾不能作為主要防禦手段,僅可作為「臨時虛擬補丁」在無法修改程式碼的舊系統上緩解風險,並需嚴格記錄、追蹤、計劃替換。
' ❌ 危險:字串拼接
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()
// ❌ 危險
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);
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 |
| 開發流程 | 靜態掃描 (SonarQube)、Code Review 清單、安全編碼培訓 | 規則: S2077, S3649, S5147 |
| 運行時 | RASP 監控異常 SQL 模式、資料庫活動監控 (DAM) | Imperva, Guardium, 開源 DBShield |
SQL 注入的根因是「資料與代碼未分離」。參數化查詢 從語法層面徹底切斷攻擊路徑,是唯一正確、標準、可維護的解法。黑名單過濾函數只能作為遷移期間的臨時緩解,決不可長期依賴。建立「安全左移」文化:需求階段威脅建模、編碼階段參數化規範、測試階段自動掃描、上線後持續監控,才能從根本消除注入風險。