新聞中心
背景
ThoughtWorks安全團隊曾經(jīng)在可信Frimware領(lǐng)域做了一些探索和研究。背景大概是這樣的:整車制造過程中,常常會引入供應商的部分設(shè)備,如車載娛樂系統(tǒng),但是出于知識產(chǎn)權(quán)的原因,這些供應商很難提供完整的源碼給整車制造方,因此二進制的固件就成了整車制造環(huán)節(jié)中的安全隱患,各種漏洞都可能被供應商的零部件引入,存在于車載系統(tǒng)之中,隨時可能被攻擊者利用而影響整車的安全性。

從網(wǎng)站建設(shè)到定制行業(yè)解決方案,為提供成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計服務體系,各種行業(yè)企業(yè)客戶提供網(wǎng)站建設(shè)解決方案,助力業(yè)務快速發(fā)展。創(chuàng)新互聯(lián)建站將不斷加快創(chuàng)新步伐,提供優(yōu)質(zhì)的建站服務。
為了探測二進制程序中的漏洞,經(jīng)過一段時間的探索和研究后,把核心技術(shù)鎖定到了符號執(zhí)行,利用該技術(shù)幫客戶搭建了一套自動化的二進制漏洞掃描平臺。并且,在后來不斷的研究中,我們發(fā)現(xiàn),符號執(zhí)行也可以用來自動化生成測試用例,為我們更加全面的編寫測試用例, 帶來新的思路。
什么是符號執(zhí)行
Wikipedia上對符號執(zhí)行的解釋:是一種程序分析技術(shù),其可以通過分析程序來得到讓特定代碼區(qū)域執(zhí)行的輸入。使用符號執(zhí)行分析一個程序時,該程序會使用符號值作為輸入,而非一般執(zhí)行程序時使用的具體值。在達到目標代碼時,分析器可以得到相應的路徑約束,然后通過約束求解器來得到可以觸發(fā)目標代碼的具體值。
講的比較繞,舉個通俗的例子來說明:假設(shè)程序現(xiàn)在是一個王者榮耀中的英雄,這個英雄經(jīng)過一定的出裝就會有一定的戰(zhàn)力(攻速,物理傷害,防御等),符號執(zhí)行的技術(shù)就是,給出了一個英雄的戰(zhàn)力,可以反推出什么樣的出裝可以達到這樣的戰(zhàn)力。
再舉個實際的代碼例子來說明符號執(zhí)行:
- void foo(int x, int y)
- {
- int t = 0;
- if( x > y ){
- t = x;
- }else{
- t = y;
- }
- if (t < x ){
- assert false;
- }
- }
假設(shè)當t 接下來,符號執(zhí)行會通過約束求解,去分析上述的每條路徑,通過約束求解分析得,如上的兩條路徑在任何情況下都不可能達到t 那我們是如何把符號執(zhí)行運用在自動化漏洞掃描的場景上? 首先要說明的是,我們要掃描的對象是Linux kernel,對于kernel來說有很多已知的CVE漏洞,我們的任務就是去發(fā)現(xiàn)二進制的kernel上是否存在這些CVE漏洞。思路如下: 由上述可知,提取漏洞的唯一特征是最重要的一步,接下來介紹如何使用符號執(zhí)行來提取漏洞指紋。 首先介紹兩個基本的概念BB(basic block)和CFG(control flow graph):BB是指從匯編的角度來看程序,一段連續(xù)的匯編指令就是一個BB,這段連續(xù)的匯編僅僅包含一個入口和一個出口,換句話說,BB內(nèi)部不會有分支和跳轉(zhuǎn)。由此我們可以得出,一個程序,是由一堆的bb組成的,它們之間有復雜的調(diào)用和跳轉(zhuǎn)關(guān)系,最終形成了一張圖,這個圖就是CFG。例如下圖是一個簡單的CFG: 有了這兩個概念,我們就可以對漏洞進行唯一的特征描述了。 由上面可知,CFG其實表示了一段程序執(zhí)行的所有路徑,而符號執(zhí)行的第一步就是去探索所有的執(zhí)行路徑。如果您了解過內(nèi)核的CVE漏洞,就會發(fā)現(xiàn)內(nèi)核很大一部分的CVE漏洞補丁,就是在一些關(guān)鍵的代碼上加了一些if分支和判斷。例如CVE-2019-19252的補丁如下: 該補丁只是在vcs_write的函數(shù)中添加了一個if判斷,對于這類補丁,在使用符號執(zhí)行生成CFG的時候,前后肯定會出現(xiàn)一個明顯的差異,因為多了一個分支,整個的程序流圖也就多了一個分支。對于這種類型的補丁,使用CFG就可以作為漏洞的特征,通過對比發(fā)現(xiàn),前后的CFG不一樣,就說明漏洞存在。 那么,僅僅通過CFG是否就可以唯一的確定這個漏洞嗎?請看下面的CVE-2019-8956的例子: 對于這種漏洞補丁,沒有分支上的增減,只是改變了一個函數(shù)的入?yún)€數(shù),那么補丁前后的CFG可能是一樣的,所以我們就不能僅僅通過CFG來判斷補丁是否存在,必須加上在語義上的分析,語義即這個參數(shù)對函數(shù)的整體影響。這就引出了符號執(zhí)行的另一步:約束求解,前面我們提到符號執(zhí)行會對所有路徑形成類似方程組的概念,然后使用約束求解器求出到達每個路徑的解的集合。如果其中某些變量發(fā)生了改變,其最終的解一定是不一樣的,以此作為漏洞標識的另一個特征。 所以最終,我們是采用符號執(zhí)行從CFG和語義分析兩個維度來唯一的確定一個漏洞的特征,然后用這個唯一的特征去目標的kernel中對比。以此來確定補丁是否已經(jīng)存在。這個就是我們檢測二進制漏洞的關(guān)鍵技術(shù),大致流程如下圖: 在整個過程中,我們會使用開源的符號執(zhí)行引擎和約束求解器,比如Angr和Z3。 前面是符號執(zhí)行在漏洞提取和掃描的一個案例,除此之外,符號執(zhí)行在漏洞挖掘,CTF等方面也有比較廣泛的應用。例如如下程序是我用Ghidra逆向的一道CTF的題目: 可以發(fā)現(xiàn),其核心關(guān)鍵是去破解這個加解密的算法(異或,加減等操作),如果人工逆向,可能需要很長時間的推算和嘗試,而符號執(zhí)行則可以自動的去不斷嘗試每個路徑的解,直到算出一個自己需要的值。有興趣的讀者,可以使用angr和z3去做一下這個CTF的破解,非常容易,這里不再贅述。需要說明的是,在破解和CTF中,符號執(zhí)行往往和IDA/Ghidra等工具來配合使用。 另一方面是在測試領(lǐng)域,在單元測試中代碼覆蓋率往往被用于評估代碼的測試充分性水平,在軟件工業(yè)界,人工設(shè)計測試用例的方法被廣泛使用,即依靠人對程序代碼的理解設(shè)計測試用例,但對應的人力成本很高,有時候為了降低人力成本且提高自動化程度,隨機測試的方法也被常常使用,但一般只能檢測到有限的程序行為,容易遺漏軟件錯誤。 在單元測試中,常用的白盒測試的充分性準則大多屬于基于控制流的覆蓋準則,如語句覆蓋,分支覆蓋和MC/DC覆蓋等。而測試準則的選取一般根據(jù)實際的測試需求而確定,比如,傳統(tǒng)軟件的測試一般要求實現(xiàn)盡可能高的語句覆蓋和分支覆蓋,而對于航天,軌交等控制軟件一般要求代碼滿足100%的分支覆蓋。而這種同時實施多種測試標準的需求,進一步加大了單元測試的工作量和難度, 使得單元測試在實際軟件開發(fā)中往往被忽略,最終導致軟件缺陷沒有在早期被及時發(fā)現(xiàn)。 而符號執(zhí)行的特點是會盡可能的遍歷每條路徑,每一次符號執(zhí)行的結(jié)果等價于大量的測試案例。符號執(zhí)行為軟件的各種情況自動生成了有效的輸入,覆蓋率高,可以更加容易檢測到程序是否存在缺陷和錯誤。所以,其實我們可以運用符號執(zhí)行生成測試用例。 目前學術(shù)界有不少的論文研究如何使用符號執(zhí)行自動化生成更好的測試用例。也有一些有意思的demo,可以讓您體驗: 以上是我們對符號執(zhí)行的一些探索,歡迎您與我們一起進行更加深入的研究。隨著大家對安全的越來越重視,基于符號執(zhí)行的漏洞掃描,自動測試,fuzz測試等越來越受到人們的重視。2019年美國《國防法》National Defense Act的H.R.5515—517 就推薦使用二進制分析和符號執(zhí)行工具來增強關(guān)鍵軟件系統(tǒng)的安全。
使用符號執(zhí)行進行漏洞掃描
漏洞指紋特征
漏洞掃描總結(jié)
符號執(zhí)行的其他應用場景
總結(jié)
網(wǎng)站標題:符號執(zhí)行,從漏洞掃描到自動化生成測試用例
轉(zhuǎn)載注明:http://www.5511xx.com/article/dpdopse.html


咨詢
建站咨詢
