您好,登錄后才能下訂單哦!
如何構造CodeDB來探索全新的白盒靜態掃描方案,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
我用了一個簡單的例子描述了一下基于.QL的掃描思路,但實際在這個領域我可能只見過一個活的SemmleQL(也就是CodeQL的原型)。下面我聊一聊這相關的東西,也分享一些我嘗試探索的一些全新的靜態掃描方案。
QL全稱Query Language,是一種用于從數據庫查詢數據的語言。我們常見的SQL就是QL的一種,這是一個很常見的概念。
而.QL是什么呢?Wiki上的解釋是,一種面向對象的查詢語言,用于從關系數據庫中檢索數據。
而.QL又和靜態分析有什么關系呢?我們需要理解一個概念叫做SCID。
SCID: Source Code in Database 是指一種將代碼語法解析并儲存進代碼中的操作方法。而這種數據庫我們可以簡單的稱之為CodeDB。
當我們通過一種方案生成了CodeDB之后,我們就需要構造一種QL語言來處理它。當然CodeQL正是一種實現了CodeDB并設計好了相應的QL語言的平臺。而Semmle QL設計的查詢語言就是一種.QL,它同時符合了幾種特點其中包括SQL、Datalog、Eindhoven Quantifier Notation、Classes are Predicates其中涵蓋了針對代碼的不同邏輯而使用的多種解決方案。當然,本文并不是要討論CodeQL,所以這里我們并不深入解釋Semmle QL中的解決方案。
.QL的概念最早在2007年被提出,詳情可以參考:
https://help.semmle.com/home/Resources/pdfs/scam07.pdf
在《從0開始聊聊自動化靜態代碼審計工具》中我曾經把基于.QL的認為是未來白盒發展的主要趨勢,其主要原因在于現代普遍使用的白盒核心技術存在許多的無解問題,在上一篇文章中,我主要用一些基于技術原理的角度解釋了幾種現代的掃描方案,今天我就從技術本身聊聊這其中的區別。
其實我在前文中提到的兩種分析方式,無論是基于AST的分析、還是基于IR/CFG的分析方式,他們的區別只是技術基礎不同,但分析的理論差異不大,我們可以粗略的將它們統一叫做Data-flow analysis,也就是數據流分析(污點分析可以算作是數據流分析的變種)。
數據流分析有很多種種類,其本質是流敏感的,且通常來說是路徑不敏感的。當然,這并不是絕對的,我們可以按照敏感類型將其分類:
流敏感分析:flow-sensitive,考慮語句的執行先后順序,這種分析通常依賴CFG控制流圖。
路徑敏感分析:path-sensitive,不僅考慮語句的執行順序,還要分析路徑的執行條件(比如if條件等),以確定是否存在可實際運行的執行路徑。
上下文敏感分析:context-sensitive,屬于一種過程間分析,在分析函數調用目標時會考慮調用上下文。主要面向的的場景為同一個函數/方法在不同次調用/不同位置調用時上下文不同的情況。
當然,需要注意的是,這里僅指的是數據流分析的分類方式,與基于的技術原理無關,如果你愿意,你當然也可以基于AST來完成流敏感的分析工具。
在基于數據流的掃描方案中,如果能夠完整的支持各種語法充足的分析邏輯,我們就可以針對每一種漏洞分析相應的數據流挖掘漏洞。可惜事實是,問題比想象的還要多。這里我舉幾個可能被解決、也可能被暫時解決、也可能沒人能解決的問題作為例子。
1、如何判斷全局過濾方案?
2、如何處理專用的過濾函數未完全過濾的情況?
3、如何審計深度重構的框架?
4、如何掃描儲存型xss?
5、如何掃描二次注入?
6、如何掃描eval中出現的偽代碼邏輯?
現代掃描方案不斷進步的同時,或許許多問題都得到一定程度的解決,但可惜的是,這就像是掃描方案與開發人員的博弈一樣,我們永遠致力于降低誤報率、漏報率卻不能真正的解決,這樣一來好像問題就變得又無解了起來……
當然,.QL的概念的掃描方案并不是為了解決這些問題而誕生的,可幸運的是, 從我的視角來看,基于.QL概念的掃描方案將靜態掃描走到了新的路中,讓我們不再拘泥于探討如何處理流敏感、約束方案等等。上次我簡單解釋了基于.QL掃描方式的原理。
其核心的原理就在于通過把每一個操作具象化模板化,并儲存到數據庫中。比如
a($b);
這個語句被具象為
Function-a FunctionCall ($b)
然后這樣的三元組我們可以作為數據庫中的一條數據。
而當我們想要在代碼中尋找執行a函數的語句時,我們就可以直接通過
select * from code_db from where type = 'FunctionCall' and node_name = 'Function-a';
這樣的一條語句可以尋找到代碼中所有的執行a函數的節點。
當然,靜態分析不可能僅靠這樣的簡單語句就找到漏洞,但事實就是,當我們針對CodeDB做分析的時候,我們既保證了強代碼執行順序,又可以跨越多重壁壘直接從sink點出發做分析,當相應的QL支持越來越多的高級查詢又或者是自定義高級規則之后,或許可以直接實現。
select * where { Source : $_GET, Sink : echo, is_filterxss : False, }
也正是因為如此,CodeQL的出現,被許多人認為是跨時代的出現,靜態分析從底層的代碼分析,需要深入到編譯過程中的方式,變成了在平臺上巧妙構思的規則語句,或許從現在來說,CodeQL這種先鋪好底層的方式并不能直接的看到效果,可幸運的是,作為技術本身而言,我們又有了新的前進方向。
下面的文章,我們就跟著我前段時間的一些短期研究成果,探索一下到底如何實現一個合理的CodeDB。
在最早只有Semmle QL的時候我就翻看過一些paper,到后來的LGTM,再到后來的CodeQL我都有一些了解,后來CodeQL出來的時候,翻看過一些人寫的規則都距離CodeQL想要達到的目標相去甚遠,之后就一直想要自己試著寫一個類似的玩具試試看。這次在更新KunLun-M的過程中我又多次受制于基于AST的數據流分析的種種困難,于是有了這次的計劃誕生。
為了踐行我的想法,這次我花了幾個星期的事件設計了一個簡易版本的CodeDB,并基于CodeDB寫了一個簡單的尋找php反序列化鏈的工具,工具源碼詳見:
https://github.com/LoRexxar/Kunlun-M/tree/master/core/plugins/phpunserializechain
在聊具體的實現方案之前,我們需要想明白CodeDB到底需要記錄什么?
首先,每一行代碼的執行順序、所在文件是基本信息。其次當前代碼所在的域環境、代碼類型、代碼相關的信息也是必要的條件。
在這個基礎上,我嘗試使用域定位、執行順序、源節點、節點類型、節點信息這5個維度作為五元組儲存數據。舉一個簡單的例子:
test.php <?php $a = $_GET['a']; if (1>0){ echo $b; }
上面的代碼轉化的結果為
test_php 1 Variable-$a Assignment ArrayOffset-$_GET@a test_php 2 if If ['1', '>', '0'] test_php.if 0 1 BinaryOp-> 0 test_php.if 1 echo FunctionCall ('$a',)
由于這里我主要是一個嘗試,所以我直接依賴SQL來做查詢并將分析邏輯直接從代碼實現,這里我們直接用sql語句做查詢。
select * from code_db where node_type='FunctionCall' and node_name='echo'
用上述語句查詢出echo語句,然后分析節點信息得到參數為$a
。
然后通過
select * from code_db where node_locate = 'test_php.if' and node_sort=0
來獲取if的條件信息,并判斷為真。
緊接著我們可以通過SQL語句為
select * from code_db where node_name='$a' and node_type='Assignment' and node_locate like 'test_php%' and node_id >= 4
得到賦值語句,經過判斷就可以得到變量來源于$_GET
。
當然,邏輯處理遠比想像的要復雜,這里我們舉了一個簡單的例子做實例,通過sort為0記錄參數信息和條件信息,如果出現同一個語句中的多條指令,可能會出現sort相同的多個節點,還需要sort和id共同處理...
這里我嘗試性的構造了基于五元組的CodeDB生成方案,并通過一些SQL語句配合代碼邏輯分析,我們得到了想要掃描結果。事實上,雖然這種基于五元組的CodeDB仍不成熟,但我們的確通過這種方式構造了一種全新的掃描思路,如果CodeDB構造成熟,然后封裝一些基礎的查詢邏輯,我們就可以大幅度解決我在KunLun-M中遇到的許多困境。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。