SQL 注入(SQL Injection)是 Web 應用程式最常見且危害最大的安全漏洞之一。駭客透過在輸入欄位、URL 參數或 Cookie 中植入惡意 SQL 片段,繞過應用程式的邏輯檢查,直接操控後端資料庫執行非預期的查詢、修改甚至刪除操作。
當開發人員未對使用者輸入進行嚴格驗證與參數化處理,直接將輸入拼接到 SQL 字串中時,資料庫會將攻擊者提供的惡意字串視為合法 SQL 指令的一部分而執行。例如:
-- 原本程式碼
String sql = "SELECT * FROM users WHERE username = '" + input + "' AND password = '" + pwd + "'";
-- 攻擊者輸入:admin' --
-- 實際執行 SQL 變為:
SELECT * FROM users WHERE username = 'admin' --' AND password = 'xxx'
-- 註解符號 -- 導致密碼驗證被忽略,直接以 admin 身分登入
'、雙引號 "、分號 ;、註解符號 -- 等,觀察頁面回應錯誤訊息或行為異常。@@version、version()、sqlite_version())或系統表差異識別後端 DBMS。UNION SELECT、盲注、錯誤回顯等技術,竊取資料庫結構、帳號密碼、敏感資料。xp_cmdshell)、寫入 Web Shell、修改登入機制以取得伺服器控制權。| 類型 | 特徵 | 範例 |
|---|---|---|
| 聯集注入 | 利用 UNION 合併多個查詢結果 | ' UNION SELECT null, username, password FROM users-- |
| 錯誤型注入 | 透過故意製造錯誤讓資料庫吐出資料 | ' AND 1=CONVERT(int, (SELECT TOP 1 name FROM sysobjects))-- |
| 布林盲注 | 根據頁面真/假回應逐位推測資料 | ' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE id=1)='a'-- |
| 時間盲注 | 利用延遲函數判斷條件真假 | '; IF (SELECT TOP 1 name FROM sysobjects)='a' WAITFOR DELAY '0:0:5'-- |
| 堆疊查詢 | 支援多語句執行的資料庫可直接執行 DDL/DML | '; DROP TABLE users;-- |
-- Java (PreparedStatement)
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
-- C# (SqlCommand)
string sql = "SELECT * FROM users WHERE username = @user AND password = @pwd";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@user", username);
cmd.Parameters.AddWithValue("@pwd", password);
xp_cmdshell、sp_OACreate 等)。生產環境關閉詳細錯誤回顯,統一導向友善錯誤頁面,避免洩露資料庫結構、SQL 片段等敏感資訊。
部署 Web 應用程式防火牆(WAF)攔截已知攻擊特徵;定期使用自動化掃描工具(如 SQLMap、OWASP ZAP)進行滲透測試。
SQL 注入並非高深技術,而是開發疏忽造成的經典漏洞。掌握參數化查詢、最小權限、輸入驗證三大核心防禦,即能有效杜絕 99% 以上的注入風險。安全是系統設計的基因,而非事後補丁。