在 SQL 注入攻擊中,錯誤回顯是判斷注入點、提取資料的關鍵線索。所謂錯誤回顯,指的是與正常頁面不同的結果反饋。資深攻擊者極其重視這一點,因為它對精準判斷注入點至關重要。本文將系統探討 SQL 注入中常見的三類錯誤——邏輯錯誤、語法錯誤、腳本運行錯誤——及其產生原理,並說明如何結合利用它們。
最典型的例子是 1=1 與 1=2。假設原始查詢為 select * from news where id=$_GET[id]:
or 1=1 有時會導致頁面內容變化的原因。歸根結底,邏輯錯誤利用的是 結果集不同 造成的頁面表現差異,靈活掌握這一原理是關鍵。
語法錯誤在 SQL Server、PostgreSQL、Sybase 等資料庫中極具價值,因為其詳細的錯誤提示可快速獲取資料庫結構信息。語法錯誤可能導致 SQL 執行中斷,但若腳本或服務器配置屏蔽了錯誤顯示,程式會繼續執行,此時返回的結果集不存在(連 NULL 都算不上),攻擊者看到的往往是「結果集為空」的假象。Oracle 和 PostgreSQL 在此情況下同樣可能表現為 "null" 字符。
典型案例是利用 MySQL 的 benchmark() 函數導致腳本執行超時,從而獲取物理路徑;或利用超時時間差異作為盲注的判斷依據(True/False 表徵)。
當頁面表徵不明顯時,可利用 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') 因類型不匹配拋出語法錯誤。可惜支援 iff 的資料庫較少。
舊式驗證 SQL:select top 1 * from admin where username='$username' and password=md5('$passWord')。注入 ' or '=' 使語句返回一條記錄,驗證通過。
現代驗證常先查用戶再比對密碼:select top 1 * from admin where username='$username'。此時 ' or '=' 雖產生結果集(admin 表第一行),但後續密碼比對失敗。解決思路:利用 UNION SELECT 構造包含已知密碼雜湊的結果集:
' and (1=2) union select top 1 username, '123456的md5值', id from admin where username='admin
使查詢返回 admin 帳號但密碼欄位為攻擊者已知的雜湊值,從而以 admin/123456 登錄並繼承權限。這也是早期 eWebEditor 等上傳漏洞利用 UNION 操作結果集的經典案例。