無法 100% 杜絕 SQL 注入,但可透過 **資料庫端強化、應用端開發規範、持續檢測回應** 三大面向,將攻擊衝擊半徑壓縮至最小。本文整理業界公認最佳實踐清單。
面向一:資料庫端強化 (DBA 責任)
1. 架構隔離:資料庫與 Web 伺服器物理/邏輯分離
- 不同主機、不同 VLAN、不同安全群組
- 資料庫伺服器**禁止直接連線網際網路**,僅允許應用伺服器 IP 入站 (防火牆/安全群組/NSG)
- 啟用 IPsec/私有鏈路加密通訊
2. 最小權限連線帳號
- 每個應用獨立資料庫帳號,**嚴禁 sa、db_owner、sysadmin**
- 權限原則:
GRANT EXECUTE ON SPECIFIC_PROC TO AppUser + DENY ALL ON TABLES TO AppUser
- 唯讀服務帳號僅授
db_datareader 或 SELECT ON View
3. 移除攻擊面
- 刪除所有範例資料庫 (
pubs, Northwind, AdventureWorks)
- 移除未使用的系統/擴展預存程序 (
sp_configure 'xp_cmdshell', 0 等)
- 停用
Ole Automation, CLR, Ad Hoc Distributed Queries 等高風險選項
4. 稽核與監控
- 啟用 SQL Server Audit:記錄
FAILED_LOGIN_GROUP, DATABASE_OBJECT_CHANGE_GROUP, EXECUTE_PROCEDURE (高風險 SP)
- 部署 Extended Events 會話捕獲長時間查詢、大量錯誤、鎖升級
- 日誌集中化 (SIEM/Log Analytics),設定告警規則
面向二:應用端開發規範 (開發者責任)
5. 參數化查詢 — 唯一正解
- 靜態 SQL + 參數綁定 (ADO.NET
SqlCommand.Parameters, Java PreparedStatement, Python cursor.execute(sql, params))
- 動態 SQL 僅在極少數情況 (動態排序/欄位) 使用,且**必須**經過白名單驗證欄位名/表名/排序方向
- ORM 使用安全模式:Entity Framework
FromSqlRaw 參數化、Hibernate createQuery 而非 createSQLQuery 字串拼接
6. 輸入驗證與輸出編碼
- 白名單驗證: 只接受預期格式 (Regex/Enum/Range),拒絕清單不可靠
- 長度限制: 資料庫欄位長度 + 業務邏輯長度雙重限制
- 統一錯誤訊息: 不回顯資料庫原始錯誤 (表名、欄位、堆疊),統一回傳「系統錯誤,請稍後再試」並記錄詳細日誌供內部追蹤
7. 安全介面與工具鏈
- 使用
SqlCommand 而非字串拼接
- 引入靜態分析 (SonarQube, Fortify, Checkmarx) 掃描 SQL 注入模式
- CI/CD 管線整合動態掃描 (OWASP ZAP, sqlmap 自動化測試)
- 資料庫與應用分離部署:應用伺服器無資料庫直接存取權,僅透過 API/服務層
面向三:持續檢測與回應 (安全運營責任)
8. 多源日誌關聯分析
- Web 伺服器日誌 (IIS/Apache/Nginx):異常參數長度、特殊字元 (
', ;, --, /*, UNION, SELECT)、HTTP 404/500 激增
- 資料庫錯誤日誌 / Audit 日誌:語法錯誤激增、權限失敗、高風險 SP 執行
- WAF/IDS/IPS 告警:規則命中、行為異常
9. 定期滲透測試與紅隊演練
- 上線前必測:OWASP Top 10 含 SQLi 全覆蓋
- 年度紅隊演練:模擬真實攻擊者從 Web 入口滲透至資料庫伺服器
- 漏洞修補 SLA:Critical (含 SQLi) 24-48 小時內修復驗證上線
總結檢查表 (每季審視一次)
| 面向 | 關鍵指標 | 目標值 |
| 資料庫 | 應用帳號權限最小化覆蓋率 | 100% |
| 資料庫 | 高風險選項 (xp_cmdshell/CLR/Ole) 停用率 | 100% (非業務必需) |
| 應用 | 參數化查詢覆蓋率 (靜態掃描) | > 99.9% |
| 應用 | 統一錯誤處理覆蓋率 | 100% |
| 運營 | 日誌集中化覆蓋率 | 100% |
| 運營 | 滲透測試發現 SQLi 修補及時率 | 100% 在 SLA 內 |
SQL 注入防禦是系統工程,非單點修補。**開發、DBA、安全、運營** 四方共同責任,持續投入,方能構建韌性防線。