SQL Injection (SQLi) 自 1998 年被公開討論至今,仍位居 OWASP Top 10 首位。本文系統說明攻擊原理、常見變體、偵測手法與**完整防禦體系**,適用於 ASP/ASP.NET/PHP/Java 等所有與資料庫互動的 Web 應用。
動態 SQL 字串拼接:
-- 危險模式
sql = "SELECT * FROM Users WHERE Username = '" + txtUser.Text + "' AND Password = '" + txtPwd.Text + "'"
攻擊者輸入:admin'-- → 實際執行:
SELECT * FROM Users WHERE Username = 'admin'--' AND Password = 'xxx'
-- 註解掉後續條件,繞過密碼驗證直接以 admin 登入。
| 類別 | 特徵 | 典型 Payload | 危害 |
|---|---|---|---|
| 經典注入 | 單引號閉合 + 邏輯控制 | ' OR 1=1--, '; DROP TABLE Users-- | 繞過驗證、資料竄改、結構破壞 |
| Union 注入 | 聯合查詢提取跨表資料 | ' UNION SELECT username,password FROM admin-- | 敏感資料洩露 |
| 錯誤回顯注入 | 利用型別轉換錯誤訊息提取資料 | ' AND 1=CONVERT(int, (SELECT TOP 1 name FROM sysobjects))-- | 結構偵察、資料外帶 |
| 盲注 | 無回顯,透過布林/時間推斷 | ' AND (SELECT SUBSTRING(@@version,1,1))='M' WAITFOR DELAY '0:0:5'-- | 繞過錯誤隱藏、WAF 繞過 |
| 二次注入 | 惡意資料儲存後被後續功能觸發 | 註冊 admin'-- → 修改密碼功能觸發更新 admin 密碼 | 繞過輸入過濾、延遲觸發 |
| 寬位元組注入 | 利用多位元組編碼繞過單引號過濾 | %bf%27 (Big5/GBK) → 過濾器見 %bf%5c,資料庫見 %bf' | 繞過 addslashes 類過濾 |
EXEC master..xp_cmdshell 'net user hacker P@ssw0rd /add'
EXEC master..xp_cmdshell 'net localgroup administrators hacker /add'
EXEC master..xp_regwrite 'HKEY_LOCAL_MACHINE',
'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe',
'Debugger', 'REG_SZ', 'C:\Windows\System32\cmd.exe'
CREATE ASSEMBLY Evil FROM 'C:\Evil.dll' WITH PERMISSION_SET = UNSAFE;
CREATE PROCEDURE EvilProc AS EXTERNAL NAME Evil.[EvilClass].Run;
(\b(union|select|insert|update|delete|drop|exec|xp_)\b) 結合上下文語意分析;-- 啟用 C2 審計追蹤或預設追蹤
-- SQL 2008+ 使用稽核規格
CREATE SERVER AUDIT SPECIFICATION Audit_SQLi
FOR SERVER AUDIT Audit_DB
ADD (FAILED_LOGIN_GROUP), ADD (SCHEMA_CHANGE_GROUP);
注意:攻擊者可在注入中加入 ;--sp_password 使追蹤記錄隱藏(sp_password 觸發記錄過濾機制)。
-- C# ADO.NET
using (SqlCommand cmd = new SqlCommand(
"SELECT * FROM Users WHERE Username = @User AND Password = @Pwd", conn))
{
cmd.Parameters.Add("@User", SqlDbType.NVarChar, 50).Value = txtUser.Text;
cmd.Parameters.Add("@Pwd", SqlDbType.NVarChar, 50).Value = txtPwd.Text;
// 參數化確保輸入永遠被視為資料,非程式碼
}
原則:**永不拼接 SQL 字串**。所有動態條件、排序、分頁皆用參數化;極少數無法參數化的識別碼(資料表名、欄位名)需嚴格白名單驗證。
^[a-zA-Z0-9_]{3,20}$);EXECUTE 特定預存程序權限,**無直接資料表 DML 權限**;sa、db_owner 連線應用程式。xp_cmdshell、xp_reg*、sp_OA* 等危險擴展程序;pubs/Northwind;customErrors mode="RemoteOnly" / debug="false";| 檢查點 | 合規標準 | 違規範例 |
|---|---|---|
| 動態 SQL 拼接 | 零容忍 | sql = "SELECT * FROM " + tableName |
| 參數化查詢覆蓋率 | 100% | 任何 WHERE/OrderBy/Top 參數未參數化 |
| 資料庫帳號權限 | 最小權限原則 | Web App 使用 sa 或 db_owner |
| 錯誤訊息回顯 | 生產環境完全隱藏 | 黃色死機畫面顯示 SQL 片段 |
| 危險擴展程序 | 已移除或撤銷 PUBLIC 執行權限 | xp_cmdshell 存在且 PUBLIC 可執行 |
SQL Injection **非技術無解之謎**,而是**開發流程缺失的必然產物**。參數化查詢 + 最小權限 + 強化配置 + 持續審計,四大支柱缺一不可。將防禦體系內化為團隊開發規範、代碼審查標準、CI/CD 閘門檢查,才能從根本上消除這個已知 20 多年的經典漏洞。