SQL 注入(SQL Injection)是 Web 應用程式中最常見也最危險的安全漏洞之一。駭客利用應用程式在構建動態 SQL 語句時,未對使用者輸入進行嚴格驗證或過濾,惡意構造特殊的輸入內容,從而改變原本 SQL 語句的邏輯,竊取、篡改甚至刪除資料庫中的敏感資料,嚴重時甚至可獲取伺服器的最高權限。
以經典的登入驗證為例,假設後端代碼直接拼接使用者輸入:
SELECT * FROM admin WHERE username='" & user & "' AND password='" & pwd & "'
若攻擊者在使用者名稱欄位輸入:1' OR '1'='1,實際執行的 SQL 將變為:
SELECT * FROM admin WHERE username='1' OR '1'='1' AND password='" & pwd & "'
因為 '1'='1' 永真,WHERE 條件恆成立,攻擊者即可繞過密碼驗證直接登入管理後台。
使用預編譯語句,將使用者輸入視為參數而非 SQL 片段,從根本上杜絕注入可能。各主流語言框架均提供完善支援(如 ADO.NET 的 SqlParameter、Java 的 PreparedStatement、PHP 的 PDO)。
雖無法完全替代參數化查詢,但作為纵深防禦的補充,應對使用者輸入進行嚴格的白名單驗證,並過濾或轉義高風險字符,例如:
'、雙引號 ";、註釋符 --、/* */SELECT、INSERT、DELETE、DROP、UPDATE、EXEC、XP_CMDSHELL 等資料庫連線帳號僅授予業務必要的最低權限,避免使用 sa 或 db_owner 等高權限帳號運行 Web 應用。
生產環境關閉詳細的資料庫錯誤回顯,防止攻擊者利用報錯資訊推斷資料庫結構。
早期 ASP/Classic 時代常見的前後端過濾寫法,僅供歷史參考,現代開發請務必採用參數化查詢。
<script language="JavaScript">
var url = location.search;
var re = /^\?(.*)(select%20|insert%20|delete%20from%20|count\(|drop%20table|update%20|truncate%20|asc\(|mid\(|char\(|xp_cmdshell|exec%20master|net%20localgroup%20administrators|"|:|net%20user|'|%20or%20)(.*)$/gi;
if (re.test(url)) {
alert("網址包含非法字符");
location.href = "error.asp";
}
</script>
<%
On Error Resume Next
Dim strTemp
If LCase(Request.ServerVariables("HTTPS")) = "off" Then
strTemp = "https://"
Else
strTemp = "https://"
End If
strTemp = strTemp & Request.ServerVariables("SERVER_NAME")
If Request.ServerVariables("SERVER_PORT") <> 80 Then
strTemp = strTemp & ":" & Request.ServerVariables("SERVER_PORT")
End If
strTemp = strTemp & Request.ServerVariables("URL")
If Trim(Request.QueryString) <> "" Then
strTemp = strTemp & "?" & Trim(Request.QueryString)
' 此處可對 strTemp 進行關鍵字過濾
%>
SQL 注入的根本原因是「代碼與資料未分離」。唯有堅持使用參數化查詢、嚴格執行最小權限、實施多層次防禦,才能有效守護資料資產。上述歷史過濾代碼僅能攔截極少量低級攻擊,現代開發中請勿將其作為核心防禦手段。