SQL 注入(SQL Injection)是發生在應用程式資料庫層的安全漏洞。簡單來說,攻擊者在輸入字串中植入惡意 SQL 指令,若程式未妥善檢查輸入,資料庫伺服器會誤將這些指令視為正常 SQL 執行,導致資料洩露、竄改甚至刪除。
許多人誤以為 SQL 注入只針對 Microsoft SQL Server,實則只要資料庫支援批次處理 SQL 指令(如 MySQL、PostgreSQL、Oracle 等),皆可能成為攻擊目標。
應用程式若存在下列情況,極易暴露於 SQL 注入風險:
sa 帳號)xp_cmdshell、OLE Automation 預存程序)SQL 指令可透過分號(;)串接多條命令;字串參數以單引號(')包裹,但連續兩個單引號('')在資料庫中視為一個單引號字元;註解符號 -- 或 /* ... */ 可使後續文字被忽略。若組合 SQL 字串時未對單引號進行轉義處理,攻擊者即可竄改原本 SQL 語法。
magic_quotes_gpc 設為 Off:新版 PHP 預設已開啟,但舊版伺服器仍可能關閉。magic_quotes_gpc 開啟與否,若缺乏輸入驗證,注入風險依然存在。當 magic_quotes_gpc = Off,提交的變數不會自動轉義單引號、雙引號、反斜線等特殊字元,攻擊者可輕易構造惡意輸入。
<?php
if (isset($_POST["f_login"])) {
// 連接資料庫...
$t_strUname = $_POST["f_uname"];
$t_strPwd = $_POST["f_pwd"];
$t_strSQL = "SELECT * FROM tbl_users WHERE username='$t_strUname' AND password = '$t_strPwd' LIMIT 0,1";
if ($t_hRes = mysql_query($t_strSQL)) {
// 成功查詢後的處理...
}
}
?>
攻擊者在使用者名稱欄位輸入 admin' --,即可繞過密碼驗證登入。
即使開啟 magic_quotes_gpc,若開發者直接將數值型欄位(如 id)未經驗證帶入 SQL,攻擊者仍可透過數字型注入(如 id=1 OR 1=1)竊取資料。
xp_cmdshell 等高危預存程序。<?php
$pdo = new PDO("mysql:host=localhost;dbname=testdb", "user", "pass");
$stmt = $pdo->prepare("SELECT * FROM tbl_users WHERE username = :uname AND password = :pwd LIMIT 1");
$stmt->execute([
':uname' => $_POST['f_uname'],
':pwd' => $_POST['f_pwd']
]);
$user = $stmt->fetch();
if ($user) {
// 登入成功
}
?>
總結:SQL 注入防禦的核心在於「永遠不信任使用者輸入」,配合參數化查詢與最小權限原則,才能從根本上杜絕風險。