傳統參數化查詢雖有效但依賴開發者自覺。本文探討三種「另類」防禦策略:語法替換、Token 隨機化、不變量驗證,從語言本質層面切斷注入路徑。
模板:SELECT * FROM T WHERE f1 = '{value1}' AND f2 = {value2}
攻擊輸入:value1=anything' OR 1=1 OR f1='whatever
結果:SELECT * FROM T WHERE f1='anything' OR 1=1 OR f1='whatever' AND f2=5
攻擊者成功改變語義,繞過原本邏輯。
SQL 具有任意性,同一語義可用不同語法表達。攻擊者注入的是標準 SQL 語法,若我們內部使用非標準語法,注入即失效。
標準:a OP1 b OP2 c
前綴:(OP1 a (OP2 b c))
模板:(SELECT * T (AND (= f1 '{value1}') (= f2 {value2})))
注入後:(SELECT * T (AND (= f1 'anything' OR 1=1 OR a='whatever') (= f2 5))) -- 語法錯誤
攻擊者真意:(SELECT * T (OR (= f1 'anything') (OR (= 1 1) (AND (= a 'whatever') (= f2 5)))))
標準:a OP1 b OP2 c
歐拉:OP1(a, OP2(b, c))
模板:SELECT(*, T, AND(=(f1, '{value1}'), =(f2, {value2})))
注入同樣導致語法錯誤
標準:a OP1 b OP2 c
物件:a.OP1(b).OP2(c)
模板:T.WHERE(f1.='{value1}').AND(f2.={value2}).SELECT(*)
注入同樣失效
將 SQL 關鍵字映射為隨機生成的 Token,每次部署/啟動重新生成:
映射表:
SELECT → iph0ohKi
* → ieZoh4xa
FROM → aeZi5uja
WHERE → OoJ4aX4n
= → eeQu2Zad
...
操作數包裝:T → @phai1Oa6@T@
最終語句:
iph0ohKi ieZoh4xa aeZi5uja @phai1Oa6@T@ OoJ4aX4n @phai1Oa6@f1@ eeQu2Zad '{value1}' @phai1Oa6@and@ @phai1Oa6@f2@ eeQu2Zad {value2}
攻擊者注入的 OR、= 在隨機語法中均為非法 Token,無法構造有效語句。
模板 Token 總數固定(例:12 個)。填充後若 Token 數變化(如變 20 個),即判定被注入。
原模板:[SELECT][*][FROM][T][WHERE][f1][=][{value1}][AND][f2][=][{value2}] = 12 tokens
注入後:[SELECT][*][FROM][T][WHERE][f1][=][anything][OR][1][=][1][OR][a][=][whatever][AND][f2][=][5] = 20 tokens
→ 違反不變量,拒絕執行
其他可驗證不變量:AST 節點數、語法樹深度、關鍵字出現次數等。
安全本質是提高攻擊成本,語法隨機化與不變量驗證從根本上改變了攻擊者的成本結構。