漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

合天智匯發表於2020-08-28

本文首發於“合天智匯”公眾號  作者: 萌新

軟體漏洞的挖掘一直是熱門的方向,安全從業者們從一開始的手工挖洞,到後來編寫自己的工具實現自動化的漏洞挖掘,再到隨著近年來AI的蓬勃發展,開始使用深度學習等技術輔助漏洞挖掘,乃至更進一步使用相關技術實現自動化攻防,如DARPA的CGC大賽等。技術日新月異,讓人眼花繚亂,本系列文章希望通過介紹典型的代表性工作(側重於安全學術界的Big4,即四大頂會上發表的成果),來幫助各位師傅們釐清脈絡和相關技術,為之後的學術發展或職業發展給出指引,能找到可以深入挖掘發展的方向。

1

按照傳統的分類方法,可以分為靜態和動態漏洞挖掘技術。

靜態漏洞挖掘技術指在不執行目標程式的前提下對目標程式進行分析,這裡又可以分為針對原始碼以及針對二進位制程式進行分析其詞法、語法、語義等,並通過相關工具獲得其AST, CFG, DDG, PDG, CPG等進行輔助分析,來挖掘漏洞。

  • 1.1

AST即抽象語法樹(Abstract Syntax Tree,AST),或簡稱語法樹(Syntax tree),是原始碼語法結構的一種抽象表示。它以樹狀的形式表現程式語言的語法結構,樹上的每個節點都表示原始碼中的一種結構。

當初學習C語言寫過的輾轉相除法的程式碼為:

 

    while b ≠ 0

        if a > b

            a := a − b

        else

            b := b − a

return a

對應的抽象語法樹為:

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

 

  • 1.2

CFG即控制流圖(Control flow graph),是一個過程或程式的抽象表現,是用在編譯器中的一個抽象資料結構,由編譯器在內部維護,代表了一個程式執行過程中會遍歷到的所有路徑。它用圖的形式表示一個過程內所有基本塊執行的可能流向, 也能反映一個過程的實時執行過程。下圖是一個包含了if和while語句的CFG

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

提到CFG,很多人都會想到CFI(Control Flow Integrity)控制流完整性技術,這是為了抵禦控制流劫持攻擊而提出的。我們知道早期的攻擊會採用程式碼注入的方式,通過部署一段shellcode,然後將控制轉向這段程式碼執行,為了組織這類攻擊,開發了DEP(Data Execution Prevention)機制來限制記憶體頁不能同時具備寫和執行許可權。攻擊者為了突破DEP,來發明瞭基於程式碼重用攻擊的技術,利用被攻擊程式中的程式碼片段進行拼接形成攻擊邏輯,此類技術包括Ret2libc,ROP,JOP等等,並且被證明為圖靈完備的。在可計算性理論裡,如果一系列運算元據的規則(如指令集、程式語言、細胞自動機)可以用來模擬任何圖靈機,那麼它是圖靈完備的。換句話說,原先的部署shellcode在跳轉執行的技術可以做的一切攻擊行為,ROP都能做到。

 

  • 1.3

DDG即資料依賴圖(Data flow dependency graph)以最簡單的形式表示各個指令之間的資料依賴關係。這樣的圖中的每個節點代表一條指令,並稱為“原子”節點。也可以將它們之間具有簡單的def-use依賴關係的某些原子節點組合為包含多指令的較大節點。

 

以這段為例:

for (int i = 1; i < n; i++) {

  b[i] = c[i] + b[i-1];

}

 

程式碼中是一個迴圈體,通過多個def-use依賴關係和記憶體訪問依賴關係構建出的DDG如下

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

 

  • 1.4

PDG,即程式依賴圖(Program Dependence Graph),是程式的一種圖形表示,它是帶有標記的有向多重圖。系統程式依賴圖是軟體程式間控制依賴關係和資料依賴關係的圖形表示。

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

 

  • 1.5

CPG程式碼屬性圖(Code Property Graph)是由ShiftLeft先提出來的,如下所示

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

CPG為每個應用唯一的程式碼版本提供可擴充套件的和多層的邏輯表示,包括控制流圖、呼叫圖、程式依賴圖、目錄結構等。CPG建立了程式碼的多層三維表示,具有很強的洞察力,這使得開發人員可充分了解應用程式每個版本執行的內容及可能帶來的風險。

 

2

先來看看靜態分析方面針對原始碼的研究。針對原始碼的漏洞挖掘主要分為兩類,分別基於中間表示和基於邏輯推理。

  • 2.1

基於中間表示的分析技術主要包括資料流分析、控制流分析、汙點分析、符號執行等。事實上,這些技術手段往往會同時應用在研究工作中。

  • 2.1.1

資料流分析是一項編譯時使用的技術,它能從中收集程式的語義資訊,並通過代數的方法在編譯時確定變數的定義和使用。通過資料流分析,可以不必實際執行程式就能夠發現程式執行時的行為。簡單地說,資料流分析就是對程式中資料的使用、定義及其之間的依賴關係等各方面的資訊進行收集的過程,以點(5)進行資料流分析如下

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘
  • 2.1.2

控制流分析的目標是得到程式的一個控制流圖(control  flow  graph)。控制流圖是對程式執行時可能經過的所有路徑的圖形化表示。通過根據不同語句之間的關係,特別是考慮由“條件轉移”、“迴圈”等引入的分支關係,對過程內的一些語句進行合併,可以得到程式結構。控制流圖是一個有向圖:圖中的結點對應於程式中經過合併的基本語句塊,圖中的邊對應於可能的分支方向,例如條件轉移、迴圈等等,這些都是分析程式行為的重要資訊。

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘
  • 2.1.3

汙點分析是一種跟蹤並分析汙點資訊在程式中流動的技術,其分析物件是汙點資訊流。汙點指的是受到汙染的資訊。在程式分析中,將來自程式之外並且進入程式的資訊當做汙點資訊,。根據分析的需要,程式內部使用的資料也可作為汙點資訊,並分析其對應的資訊的流向。根據汙點分析時是否執行程式,可以將其分為靜態汙點分析和動態汙點分析。

汙點分析的過程包括:識別汙點資訊在程式中的產生點並對汙點資訊進行標記;利用特定的規則跟蹤分析汙點資訊在程式中的傳播過程;在一些關鍵的程式點檢查關鍵的操作是否會受到汙點資訊的影響。汙點資訊的產生點稱為source點,汙點資訊的檢查點稱為sink點。

以下圖為例來說明汙點分析過程

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

將scanf所在的程式點作為source點,將通過scanf接收的使用者輸入資料標記為汙點資訊,並且認為存放它的變數x是被汙染的。如果在汙點傳播規則中規定“如果二元操作的運算元是汙染的,那麼二元操作的結果也是汙染的”,則對於y=x+k,由於x是汙染的,因此y也被認為是汙染的。一個被汙染的變數如果被賦值為一個常數,它將被認為是未汙染的。對於x=0,將x從汙染狀態轉變為未汙染。對於while(i<y),這句所在的程式點在這裡被認為是一個sink點,如果汙點分析規則規定“迴圈的次數不能受程式輸入的控制”,那麼在這裡就需要檢查變數y是否是被汙染的。

 

  • 2.1.4

符號執行是一種用符號值代替數字值執行程式的技術,符號是表示一個取值集合的記號。使用符號執行分析程式時,對於某個表示程式輸入的變數,通常使用一個符號表示它的取值,這個符號可以表示程式在此處接收的所有可能的輸入。此外,在符號執行的分析過程中那些不易或者無法確定取值的變數也常常使用符號表示的方式進行分析。

符號執行的分析過程大致如下:首先將程式中的一些需要關注但是又不能直接確定其取值的變數用符號表示其取值,然後通過逐步分析程式可能的執行流程,將程式中變數的取值表示為符號和常量的計算表示式。程式的正常執行和符號執行的主要去唄是:正常執行時程式中的變數可以看做被賦予了具體的值,而符號執行時,變數的值既可以是具體的值也可以是符號和常量的運算表示式。

以下圖的符號執行原始碼為例,函式中的引數x,y分別用符號a,b表示

 

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

基於上圖的程式碼可以得到下圖所示的程式流程圖

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

 

可以看到共有三條執行路徑,每條路徑都對應著一個路徑約束(path constrain,PC)。其中返回true的路徑有一條,帶入符號後,對應的路徑約束為a>60&(b*2)==128;返回false的路徑有兩條,對應的路徑約束為a<=60|(a>60&(b*2)!=128)

這個例子表明,使用符號執行技術分析程式,對於分析過程中遇到的程式中帶有條件的控制轉移語句(條件分支語句、迴圈語句等),可以利用變數的符號表示式將控制轉移語句中的條件轉化為對符號取值的約束,通過分析約束是否可以滿足,判斷程式的哪條路徑是可行的。這一部分是符號執行分析的關鍵部分。由此將判斷路徑條件是否可滿足的問題轉化為判斷符號取值的約束是否可滿足的問題。而對於約束是否可滿足的判斷,通常使用約束求解的方法,該過程由約束求解器完成(約束求解器是對特定形式的約束表示進行求解的工具)。在符號執行的分析過程中,常使用可滿足性模理論(satisfiabilti modulo therries,SMT)求解器對約束進行求解,為此需要將符號取值約束的求解問題轉為SMT問題,即一階邏輯的可滿足性判斷問題。

  • 2.2

基於邏輯推理的漏洞檢測方法將原始碼進行形式化描述,然後利用數學推理、證明等方法

驗證形式化描述的一些性質,從而判斷程式是否含有某種型別的漏洞。基於邏輯推理的漏洞檢測方法由於以數學推理為基礎,因此分析嚴格,結果可靠。但對於較大規模的程式,將程式碼進行形式化表示本身是一件非常困難的事情。所以實際上研究價值相對來說並不大。

 

3

相關工作

這裡分別介紹針對原始碼的靜態漏洞挖掘技術部分代表性工作。

  • 3.1基於中間表示

發表在2018 NDSS(資訊保安四大頂會之一)的K-Miner利用核心程式碼中高度標準化的介面實現了可擴充套件性良好的指標分析以及全域性的上下文敏感的分析技術,支援對空指標引用、指標釋放後重引用(use-after-free, UAF)、指標重釋放(double free)、雙重檢查鎖定(double-checked lock)等記憶體崩潰漏洞的檢測。論文及論文作者在會議上的視訊見文後給出的參考連結

其實現如圖

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

具體來說,它包括四個分析階段:在步驟1中,LLVM-IR作為vmlinux bitcode映像傳遞到K-Miner,以開始進行預分析,這將初始化並填充全域性核心上下文。在步驟2中,此上下文資訊用於分析單個系統呼叫,這可以連續多次執行,比如可以分析dangling pointer,use-after-free和double free。在步驟3中,通過各種驗證技術對錯誤報告進行了清理,以降低誤報率。在第4步中,使用我們的漏洞報告引擎呈現已排序的報告。

 

在實驗中,K-Miner發現了29處可能的漏洞,總共生成了539個alert,如下所示

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘
  • 3.2基於邏輯推理

近年來個人沒有看到有相關的工作,不過為了文章的完整性,這裡介紹CCS 2002(CCS同樣是四大頂會之一)的工作-MOPS。

論文中作者首先確定安全程式設計實踐的規則,將其編碼為安全屬性,並驗證是否遵守這些屬性。由於手動驗證過於繁瑣,因此建立了程式分析工具來自動完成此過程。程式將要驗證的程式分析建模為下推式自動機,將安全屬性表示為有限狀態自動機,並使用模型檢查技術來確定在程式中是否可以達到違反預期安全目標的任何狀態。

全文邏輯縝密,單單幾張圖說不清楚,建議有興趣的師傅們自己去看看這篇論文,下面給出一個簡單的例子,以程式許可權系統呼叫為例。

程式許可權模型如下

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

存在風險的系統呼叫模型如下

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

描述該屬性的複合模型,即在特權狀態下,程式不應進行有風險的系統呼叫。

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

當然,上面是非常簡化的版本,建模越精細,效果自然越好。將linux 2.4.17中的程式許可權模型建模如下(包括所有的rued,euid,suid等)

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

建模之後,文中以一個例項進行了說明

在wu-ftpdversion 2.4中找到了一個已知的安全漏洞。漏洞除了分別在訊號SIGPIPE和SIGURG的處理程式中呼叫seteuid(0)和longjmp(env),基本類似於下圖程式碼中的漏洞

漏洞挖掘的藝術-面向原始碼的靜態漏洞挖掘

通過在訊號SIGPIPE之後立即將訊號SIGURG傳送到awu-ftpd程式,攻擊者可以使該程式呼叫訊號SIGPIPE的處理程式中的seteuid(0)獲得特權,然後呼叫訊號SIGURG的處理程式中的longjmp(env)返回到函式main中的setjmp(env)的呼叫處。 此後,wu-ftpd將使用root特權執行,從而導致攻擊者具有root特權。

MOPS能夠在wu-ftpd2.4 beta 11中成功檢測到該漏洞。

 

4

參考

1.https://juejin.im/post/5cc51b096fb9a03218555972

2.http://www.jos.org.cn/html/2017/10/5317.htm

3.https://llvm.org/docs/DependenceGraphs/index.html

4.https://zhuanlan.zhihu.com/p/94611033

5.https://cs.nju.edu.cn/chenlin/pages/sat/dataflow.pdf

6.http://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=10342

7.http://staff.ustc.edu.cn/~yuzhang/compiler/2017f/lectures/optimize-6in1.pdf

8.https://www.52pojie.cn/thread-861992-1-1.html

9.https://www.youtube.com/watch?v=1uLKA7Ux8hg

10.https://www.ndss-symposium.org/wp-content/uploads/2018/02/ndss2018_05A-1_Gens_paper.pdf

11.https://www.danielesgandurra.com/research/blast2008-slides.pdf

12.https://people.eecs.berkeley.edu/~daw/mops/

13.http://people.eecs.berkeley.edu/~daw/papers/mops-ccs02.pdf

5

實驗推薦

docker搭建vulhub靶場進行nginx服務漏洞分析

https://sourl.cn/kPa7hT

Docker是近兩年來十分流行的開源容器引擎,Vulhub是一個面向大眾的開源漏洞靶場。通過本實驗瞭解Docker的使用,掌握使用Vulhub靶場環境進行漏洞復現。

 

相關文章