安全研究所 | 突破語義分析的黑魔法

當下,語義分析算法因其輕規則、低誤漏報、更貼合業務場景等優勢被廣泛應用于各類型的安全防護產品中,并取得了較好的效果,但現階段依舊存在一些方法能夠有效突破傳統語義分析防護,本文會介紹部分SQL注入場景下突破語義分析算法的黑魔法。
詞法分析
現階段,SQL注入的詞法分析主流分為兩類:
基于弱規則詞法黑名單
基于詞法Token變化
其中基于弱規則詞法黑名單的算法被用于大家熟知的Libinjection,主要通過將用戶的輸入進行Token化,然后再去匹配一份維護好了的SQL注入黑名單規則庫,從而有效發現SQL注入問題。
其中各種輸入對應詞法如下:
檢測SQL注入的流程如下:
而基于Token變化的檢測算法,規則比上述算法更弱,只需計算用戶的輸入是否橫跨了多個Token,如果橫跨了多個Token則判斷為存在SQL注入。
語義分析
和詞法分析相比,語義分析會做的更加細致,它不僅僅關注SQL的Token,更會去關注用戶的輸入對具體的SQL結構造成了怎樣的改變,這樣能夠更大程度的解決詞法分析僅僅基于Token造成的誤報問題。
當用戶輸入會導致SQL整體語義發生變化,往往會被語義分析判定為SQL注入。
對于一些運行時安全防護產品而言,由于運行在應用中,可以直接獲取到完整的SQL語句,語義分析的準確率往往較高,而對于傳統流量型安全防護產品而言,由于只能獲取到流量中的用戶輸入參數,無法知道真實運行的SQL語句是什么樣的,就需要額外的工作,大體分為兩類:
SQL片段分析:
需要基于 Context Free Grammer ,最大的挑戰是時間復雜度和準確率。
構造完整的SQL語句:
主流安全產品會假設用戶輸入參數為數字型、字符型兩種場景,將參數拼接到簡化的SQL語句中構成完整的SQL語句,進而進行語義分析。但很多時候會出現關鍵字拼接參數(如IN、GROUP BY、ORDER BY等)的場景,這種情況下語義分析準確率就會下降,而如果盡可能的窮舉了用戶參數的拼接場景,則會造成性能的不可控。
預期外的SQL特性
原理
語義分析會面臨的一個最大的難題就是:雖然大部分的數據庫語法都比較相似,但不同數據庫之間又都有自己獨有的一些特性在里面,這樣如果攻擊者對某一款數據庫足夠了解,就可能通過一些特殊的SQL特性進行SQL注入,而語義分析之前又未能兼容該特性,從而導致語義分析引擎報錯,失去檢測能力。
巧用ODBC
ODBC是一個大部分SQL都支持的特性,官方介紹如下:
{identifier expr} is ODBC escape syntax and is accepted for ODBC compatibility. The value is expr. The { and } curly braces in the syntax should be written literally; they are not metasyntax as used elsewhere in syntax descriptions.
由于ODBC本身的自由性,可以構造出很多非常復雜的SQL語句,從而導致語義分析很難進行識別。
psql并不認識轉義字符
幾乎大部分主流語義分析引擎、主流數據庫都將 \ 理解為轉義字符,但PSQL并不這么理解,對 \ 理解上的差異使得繞過PSQL變得十分容易。
神奇的科學計數法
科學符號,特別是 e 符號,已被集成到包括 SQL 在內的許多編程語言中。目前還不清楚這是否是所有 SQL 實現的一部分,但它是 MySQL/MariaDB 實現的一部分。當e符號在無效的上下文中使用的時候,并不會導致SQL報錯,而是會被SQL自行忽略,這就導致了SQL注入時的Payload可以通過大量無效科學符號來影響語義分析引擎對SQL語句的解析。
select last_name from students where student_id = '1' union select concat 5.e(1.e(flag 10.2e)3.e,'***'6.e) from test 1.e.flag--
注釋欺騙的藝術
原理
大部分語義分析往往都是能夠識別出注釋,并在分析時省略注釋后面語句的分析,從而實現更好的性能,那么如果攻擊者能夠成功構造出語義分析引擎認為是注釋而實際數據庫并不認為是注釋的特殊關鍵字,再把攻擊的Payload隱藏在注釋之后,就能成功欺騙語義分析,光明正大的進行SQL注入。
萬能注釋 //
存在不少語義分析引擎,在解析數據流的時候,會將 // 作為注釋處理,忽視后面的內容,而大部分主流數據庫,并不將 // 作為注釋。
注釋結束符的差別
語義分析引擎 往往認為 \r \n 都是注釋的結束符,但很多數據庫(MYSQL\ORACLE等)只認 為 \n 是注釋結束符,利用注釋結束符理解的差異可以構造繞過。
mybatis眼中的#
JAVA的mybatis框架會對用戶輸入的參數做一些特殊的處理,尤其針對形如 #{param} 這種寫法的數據的額外處理,會對語義分析造 成極強的欺騙性。
巧用特殊關鍵字
原理
除去讓很多開發、安全人員熟知的關鍵字外,不少數據庫也擁有一些較為冷門的關鍵字,這些關鍵字在語義分析或詞法分析時很可能未能兼容,從而導致防護失效。因此,尋找冷門且有效的關鍵字也是繞過語義分析引擎的一種有效手段,尤其是針對新版本的數據庫,往往會出現一些新的關鍵字,這些關鍵字極有可能未被兼容。
handle替代select
MySQL 除了可以使用 select 查詢表中的數據,也可使用 handler 語句,這條語句使我們能夠一行一行的瀏覽一個表中的數據。它是 MySQL專用的語句,并沒有包含到SQL標準中。handler 語句由于可以查詢數據,因此也是SQL注入中一個十分方便且鮮為人知的關鍵字。
SELECT * FROM students WHERE stuname = 'glassy';Handler flag OPEN;Handler flag read first;Handler flag close;#
MEMBER OF函數
MEMBER OF()是一個MySQL8高版本特性,官方定義它是一個函數,但是這個函數的函數名中間還包含空格,十分具有欺騙性,雖然它對于注出數據并沒有什么幫助,但是放在注入Payload的前段以促使語義分析引擎解析失敗報錯卻是一個很不錯的選擇。
SELECT last_name FROM students WHERE student_id = '1' and (select substr((SELECT flag from flag), 1, 1) MEMBER OF('["a","b","t"]'))=1;
