張志威,甘 剛
(成都信息工程大學(xué)網(wǎng)絡(luò)空間安全學(xué)院,四川 成都 610225)
Android系統(tǒng)因其智能化的操作和應(yīng)用廣受各大廠商推崇與二次開發(fā),手機(jī)市場(chǎng)占有率逐年攀升。智能移動(dòng)終端承載著億萬移動(dòng)用戶的生產(chǎn)生活,良好的便攜性及系統(tǒng)生態(tài)獲得了廣大用戶的喜愛。但與此同時(shí),暴露出的Android漏洞數(shù)目也隨之增長。因此,Android系統(tǒng)的安全性也一直是安全研究人員關(guān)注的重點(diǎn)。
據(jù)CNVD(China Nation Vulnerability Database)及其他知名漏洞提交平臺(tái)查詢發(fā)現(xiàn),以往提交的Android漏洞集中于應(yīng)用層,大多為組件暴露[1]、信息泄露、二次重打包[2]、權(quán)限提升等類型,但對(duì)系統(tǒng)服務(wù)層面的研究探索較少。而Android系統(tǒng)服務(wù)作為運(yùn)行在系統(tǒng)底層的核心進(jìn)程,一旦被惡意程序獲取到相關(guān)權(quán)限,則可能會(huì)導(dǎo)致隱私泄露。此外如果服務(wù)在運(yùn)行過程中接收使用了傳入的非法參數(shù),則可能會(huì)致使系統(tǒng)重啟、拒絕服務(wù)甚至內(nèi)存損壞等不可知結(jié)果。文獻(xiàn)[3]在對(duì)Android系統(tǒng)服務(wù)漏洞挖掘的過程中使用了模糊測(cè)試的方法,但測(cè)試數(shù)據(jù)類型單一,未對(duì)通信過程中復(fù)雜的參數(shù)類型進(jìn)行構(gòu)造,某種程度上導(dǎo)致了參數(shù)用例覆蓋的不全面。文獻(xiàn)[4]同樣利用模糊測(cè)試的方法對(duì)系統(tǒng)服務(wù)進(jìn)行漏洞挖掘,但對(duì)系統(tǒng)服務(wù)中多維參數(shù)的變異[5]沒有進(jìn)行合理的控制處理,可能會(huì)導(dǎo)致組合爆炸等問題。如何解決模糊測(cè)試過程中用例覆蓋率低及多維參數(shù)變異的問題也一直是漏洞挖掘人員的研究重點(diǎn)。
因此,本文將遺傳算法與模糊測(cè)試技術(shù)結(jié)合起來,通過適應(yīng)度函數(shù)對(duì)參數(shù)進(jìn)行變異指導(dǎo),保證了參數(shù)的多樣性,并且根據(jù)數(shù)據(jù)類型變異優(yōu)先級(jí)表對(duì)不同參數(shù)也進(jìn)行相應(yīng)的組合變異操作。該方法在一定程度上減小了組合爆炸對(duì)參數(shù)遺傳變異的影響,提高了測(cè)試用例的覆蓋率。
Android終端的流暢運(yùn)行離不開系統(tǒng)服務(wù)的支持,如短信的接收與發(fā)送需要短信管理服務(wù)SmsManager,窗口的打開與關(guān)閉需要窗口管理服務(wù)WindowManager等,各種服務(wù)Manager提供對(duì)底層的訪問接口,方便了上層應(yīng)用的調(diào)用。Android系統(tǒng)服務(wù)主要分為守護(hù)進(jìn)程服務(wù)、本地系統(tǒng)服務(wù)和Java系統(tǒng)服務(wù)。守護(hù)進(jìn)程是為處理系統(tǒng)多任務(wù)請(qǐng)求而在后臺(tái)運(yùn)行的Server程序。此類進(jìn)程在系統(tǒng)啟動(dòng)初始化中生成,常駐系統(tǒng)后臺(tái),直至系統(tǒng)運(yùn)行結(jié)束。其中典型的有用于圖像合成顯示的SurfaceFlinger服務(wù)、管理Binder對(duì)象的ServiceManager等。第二類本地系統(tǒng)服務(wù)數(shù)量較少,一般使用C/C++編寫,運(yùn)行在LIBRARIES層中[6],包括AudioFlinger音頻服務(wù)、CameraService相機(jī)服務(wù)等其他重要服務(wù)。最后就是Java系統(tǒng)服務(wù),該類服務(wù)由SystemServer系統(tǒng)進(jìn)程啟動(dòng),并以線程的形態(tài)運(yùn)行在SystemServer進(jìn)程中。Java系統(tǒng)服務(wù)又分為核心平臺(tái)服務(wù)和硬件系統(tǒng)服務(wù)。核心系統(tǒng)服務(wù)提供了系統(tǒng)正常運(yùn)行基本的功能,與應(yīng)用程序交互較少,但卻是Android Framework運(yùn)行所必需依賴的。而硬件服務(wù)則為上層應(yīng)用提供接口,用于控制底層硬件提供服務(wù)。常用的Android系統(tǒng)服務(wù)如表1所示。
表1 常用系統(tǒng)服務(wù)
SystemServer進(jìn)程中運(yùn)行著諸多Java系統(tǒng)服務(wù),應(yīng)用如果想調(diào)用系統(tǒng)服務(wù),就要以跨進(jìn)程的方式與系統(tǒng)服務(wù)進(jìn)行通信。Android系統(tǒng)不同進(jìn)程間的信息交互要使用Binder通信機(jī)制,例如當(dāng)上層應(yīng)用要調(diào)用發(fā)送短信的API,其底層實(shí)現(xiàn)就是通過Binder對(duì)象調(diào)用短信的系統(tǒng)服務(wù)。每個(gè)系統(tǒng)服務(wù)中封裝定義了實(shí)現(xiàn)相應(yīng)功能的方法,而這些接口方法則是本文進(jìn)行模糊測(cè)試漏洞挖掘的研究對(duì)象。
Android為保證進(jìn)程安全采用了沙箱隔離的機(jī)制[7],但不同進(jìn)程間往往需要信息數(shù)據(jù)交換。傳統(tǒng)的通信方式如管道、消息隊(duì)列等是通過讀寫內(nèi)核緩沖區(qū)的方式獲取數(shù)據(jù),2次復(fù)制過程存在效率問題,而套接字資源開銷較大,多用于網(wǎng)絡(luò)相關(guān)傳輸。此外,這些通信方式無法確認(rèn)雙方的身份,容易被攻擊。而Binder通信機(jī)制使用內(nèi)存映射的方式只對(duì)內(nèi)容拷貝一次,發(fā)送過程中會(huì)添加身份識(shí)別ID,并且采用C-S架構(gòu),是一種安全高效的進(jìn)程通信方式[8]。系統(tǒng)服務(wù)想要被調(diào)用,要先通過Binder通信機(jī)制跨進(jìn)程在ServiceManager中注冊(cè),這樣上層就可以通過Binder對(duì)象直接從用戶空間到底層訪問服務(wù)。
Binder通信架構(gòu)主要由客戶端進(jìn)程、服務(wù)端進(jìn)程、ServiceManager、Binder驅(qū)動(dòng)4個(gè)部分組成。前3者運(yùn)行在用戶空間,服務(wù)端進(jìn)程在ServiceManager中注冊(cè)后,由客戶端進(jìn)程發(fā)出服務(wù)請(qǐng)求,進(jìn)而才能使用服務(wù)[9]。ServiceManager主要提供輔助管理的功能,而Binder驅(qū)動(dòng)運(yùn)行在內(nèi)核空間以負(fù)責(zé)各個(gè)進(jìn)程間通信。當(dāng)跨進(jìn)程通信發(fā)生時(shí),Server進(jìn)程擁有Binder對(duì)象,而Client進(jìn)程會(huì)調(diào)用其關(guān)聯(lián)BinderProxy對(duì)象實(shí)例的transact方法發(fā)起請(qǐng)求[10],通過IPC的方式傳遞到Server端。Server接收到參數(shù)后調(diào)用服務(wù)端的transact方法,最終由onTransact執(zhí)行相應(yīng)的邏輯并將結(jié)果返回給Client端。Binder通信模型如圖1所示。
圖1 Binder通信模型
模糊測(cè)試是基于黑盒的安全測(cè)試技術(shù)[11],通過向程序輸入隨機(jī)數(shù)據(jù)導(dǎo)致程序崩潰或產(chǎn)生異常,進(jìn)而發(fā)現(xiàn)應(yīng)用中的潛在漏洞。對(duì)于Android系統(tǒng)服務(wù)的模糊測(cè)試,首先要確定用例參數(shù)的數(shù)據(jù)入口。經(jīng)過分析,上層應(yīng)用對(duì)系統(tǒng)服務(wù)的調(diào)用是通過Binder實(shí)現(xiàn)的,請(qǐng)求服務(wù)都會(huì)調(diào)用到transact方法??梢钥紤]將底層transact方法作為測(cè)試入口,但該方法存在于系統(tǒng)底層,用例參數(shù)無法直接傳入,不適合作為入口的選擇。通過分析底層transact函數(shù)的上下文調(diào)用關(guān)系,發(fā)現(xiàn)Java上層Binder類實(shí)際是對(duì)底層功能實(shí)現(xiàn)的封裝,上層使用Binder調(diào)用服務(wù)會(huì)使用Binder代理類的transact方法,層層傳遞最終仍會(huì)調(diào)用到底層的transact函數(shù),且參數(shù)是原樣傳入底層。該方法符合測(cè)試接口低權(quán)限、參數(shù)透傳性好的要求,且代碼容易實(shí)現(xiàn),因此可以選擇上層Binder類的transact方法作為模糊測(cè)試的數(shù)據(jù)入口。
transact函數(shù)原型為bool transact(int code,Parcel data,Parcel reply,int flags)[4],方法返回值為布爾型。其中code是int類型,對(duì)應(yīng)的是Aidl文件中定義接口的方法號(hào),從1開始,依次遞增。data是Parcel類型,用來保存接口的各個(gè)參數(shù)數(shù)據(jù)。reply也是Parcel數(shù)據(jù)類型,用來保存服務(wù)端返回的數(shù)據(jù)。而flag為通信類型標(biāo)志位,0表示請(qǐng)求發(fā)起后需要等待返回的普通RPC(Remote Procedure Call)類型,1則表示為單向的RPC通信,即不需要接收返回信息。其中data中所存放的參數(shù)則是要進(jìn)行構(gòu)造填充Fuzz的數(shù)據(jù)。如在某服務(wù)中定義了接口號(hào)為10的方法:test(int a,String b,double c)。則transact方法的構(gòu)造如圖2所示。
圖2 transact方法構(gòu)造示例
測(cè)試模塊獲取到接口參數(shù)類型后構(gòu)造初始測(cè)試用例,并通過trancact函數(shù)調(diào)用系統(tǒng)服務(wù),然后監(jiān)控手機(jī)是否發(fā)生異常,這樣就完成一次基本的模糊測(cè)試。
遺傳算法[12]是模擬生物自然進(jìn)化的一種求解復(fù)雜問題的通用計(jì)算模型,通過適應(yīng)度函數(shù)對(duì)個(gè)體差異進(jìn)行評(píng)價(jià),從而對(duì)其進(jìn)行個(gè)體優(yōu)選、基因交叉、數(shù)據(jù)變異操作。遺傳過程中逐漸將劣質(zhì)個(gè)體淘汰,優(yōu)秀個(gè)體遺傳給下一代,使個(gè)體最終趨于最優(yōu)。本文根據(jù)系統(tǒng)服務(wù)漏洞挖掘?qū)嶋H場(chǎng)景,將遺傳算法思想巧妙運(yùn)用到測(cè)試用例的生成過程中,設(shè)計(jì)實(shí)現(xiàn)了Android系統(tǒng)服務(wù)漏洞挖掘工具ASFuzzer。該工具將單次測(cè)試結(jié)果作為適應(yīng)度函數(shù)的評(píng)判標(biāo)準(zhǔn)[13],指導(dǎo)參數(shù)進(jìn)行變異,保證了新一輪測(cè)試參數(shù)用例的有效遺傳,而對(duì)于無效的參數(shù)則拋棄并重新生成有效數(shù)據(jù);并且在單個(gè)數(shù)據(jù)變異有效的前提下,通過排列組合的方式,對(duì)不同參數(shù)也進(jìn)行相應(yīng)的變異,有效提升測(cè)試用例覆蓋率。
ASFuzzer是一款針對(duì)Android系統(tǒng)服務(wù)安全測(cè)試的半自動(dòng)化工具,可以安裝到不同Android版本系統(tǒng)進(jìn)行測(cè)試,包括谷歌原廠鏡像及第三方定制系統(tǒng)。該工具分為模糊測(cè)試和遺傳變異2個(gè)模塊。模糊測(cè)試模塊主要是對(duì)服務(wù)接口進(jìn)行測(cè)試并進(jìn)行結(jié)果反饋。該模塊首先使用反射機(jī)制獲取到系統(tǒng)服務(wù)信息,同時(shí)將服務(wù)接口、參數(shù)等信息保存在數(shù)據(jù)庫以供調(diào)用。而后,根據(jù)接口參數(shù)類型構(gòu)造生成初始測(cè)試用例,通過Binder調(diào)用transact方法對(duì)服務(wù)進(jìn)行測(cè)試,而測(cè)試結(jié)果則會(huì)輸出到日志中,最終反饋給遺傳變異模塊。遺傳變異模塊則主要對(duì)參數(shù)用例進(jìn)行優(yōu)化、變異。在獲取到前次的結(jié)果反饋后,根據(jù)相應(yīng)的策略,對(duì)單個(gè)參數(shù)或者多個(gè)參數(shù)進(jìn)行變異,然后再次循環(huán)測(cè)試,直至發(fā)現(xiàn)漏洞或到達(dá)變異次數(shù)。其整體設(shè)計(jì)框架如圖3所示。
圖3 ASFuzzer整體設(shè)計(jì)框架
該模塊功能主要對(duì)服務(wù)接口進(jìn)行測(cè)試,并將結(jié)果進(jìn)行反饋。
1)服務(wù)接口信息獲取。
系統(tǒng)服務(wù)相關(guān)信息主要是通過對(duì)ServiceManager反射來獲取的。ServiceManager是系統(tǒng)服務(wù)的管理者,其內(nèi)部維護(hù)了已注冊(cè)系統(tǒng)服務(wù)的Binder對(duì)象列表,這樣可以通過反射android.os.ServiceManager的方式獲取其對(duì)象實(shí)例,再反射[14]調(diào)用listservices方法就可以得到系統(tǒng)中運(yùn)行的服務(wù)信息。而調(diào)用getService則會(huì)得到相應(yīng)服務(wù)的Binder句柄。
對(duì)于測(cè)試用例的構(gòu)造,需要獲得測(cè)試服務(wù)的接口號(hào)及對(duì)應(yīng)參數(shù)。當(dāng)獲取到服務(wù)的Binder句柄后,可以通過反射“接口描述符+$Stub”的方法獲取服務(wù)中的各種方法屬性。其中會(huì)有以“TRANSACTION_”開頭的方法及屬性描述,而屬性中int型就是該方法對(duì)應(yīng)的接口號(hào)[4]。最后通過將接口描述符傳入Class.forname進(jìn)而反射調(diào)用getDeclaredMethods和getParameterTypes的方式獲取服務(wù)所定義的接口方法及參數(shù)類型。
2)測(cè)試用例的構(gòu)造與發(fā)送。
測(cè)試用例的構(gòu)造直接關(guān)乎數(shù)據(jù)能否順利通過目標(biāo)的參數(shù)校驗(yàn)[15]。通過對(duì)數(shù)據(jù)庫中參數(shù)類型分析統(tǒng)計(jì)可得,除了常規(guī)類型外,還有一些Binder、Component Name、Intent等系統(tǒng)類類型。對(duì)于可以構(gòu)造的參數(shù)類型,通過常識(shí)去進(jìn)行構(gòu)造或者對(duì)其進(jìn)行反射構(gòu)造函數(shù)獲取,而對(duì)于無法直接或間接構(gòu)造的類型,使用null值對(duì)其填充。為了大概率構(gòu)造異常數(shù)據(jù),初始值的選擇一般選擇邊界值或者0值附近的值,樣本初始數(shù)據(jù)構(gòu)造如表2所示。
表2 初始數(shù)據(jù)構(gòu)造表
測(cè)試用例的構(gòu)造即transact需要發(fā)送的內(nèi)容。第一個(gè)填充的是方法接口號(hào),第二個(gè)data則要填充各種類型的參數(shù)數(shù)據(jù)。但data要先填充該服務(wù)的接口描述符,以保證數(shù)據(jù)順利通過底層校驗(yàn),然后再根據(jù)參數(shù)類型選擇初始數(shù)據(jù)填充。replay默認(rèn)為空,而flag參數(shù)一般填充0。最后獲取到待測(cè)服務(wù)的Binder句柄,調(diào)用transact方法即可對(duì)接口號(hào)對(duì)應(yīng)的方法發(fā)起測(cè)試。
3)日志異常監(jiān)控。
日志異常反饋對(duì)測(cè)試用例的遺傳變異具有重要的指導(dǎo)作用[16]。ASFuzzer在測(cè)試過程中可能會(huì)出現(xiàn)各種異常,如參數(shù)不合法、Binder失活、系統(tǒng)進(jìn)程崩潰、手機(jī)重啟等其他不可知后果,因此需要對(duì)ASFuzzer及系統(tǒng)狀態(tài)進(jìn)行監(jiān)控記錄。主要記錄有2部分內(nèi)容:
①ASFuzzer模糊測(cè)試過程中所發(fā)送的測(cè)試用例,transact的返回值,replay接收服務(wù)端的返回信息,以及其他異常。該部分異常信息,需要反饋給遺傳變異模塊,作為前次測(cè)試用例的適應(yīng)度評(píng)判。
②系統(tǒng)相關(guān)日志,用來記錄系統(tǒng)崩潰或重啟以及其他未知異常。
ASFuzzer實(shí)現(xiàn)了日志記錄的功能,將測(cè)試結(jié)果等信息導(dǎo)出到文件中。這樣有利于事后快速定位異常發(fā)生的服務(wù)接口及其當(dāng)次所發(fā)送的參數(shù)等,提高了確認(rèn)漏洞的效率。
遺傳算法不斷優(yōu)化個(gè)體的思想,可以應(yīng)用到系統(tǒng)服務(wù)測(cè)試數(shù)據(jù)生成中。整體過程可分為初始化樣本,適應(yīng)度函數(shù)評(píng)價(jià)、變異、交叉、選擇等。其流程如圖4所示。
圖4 遺傳變異模塊流程
1)編碼方案與適應(yīng)度函數(shù)的確定。
編碼是將問題空間的解轉(zhuǎn)化為遺傳過程中所能識(shí)別的基因個(gè)體,是對(duì)問題解的一種表現(xiàn)形式[17]。作為遺傳算法中個(gè)體進(jìn)化變異的基礎(chǔ),編碼形式往往會(huì)根據(jù)實(shí)際問題情況而采取不同的方案。對(duì)于系統(tǒng)服務(wù)的漏洞挖掘,測(cè)試用例中的參數(shù)沒有固定的數(shù)據(jù)類型。為了更好地被底層接口識(shí)別,可以將參數(shù)類型作為編碼方案的選取,直接采用對(duì)應(yīng)數(shù)據(jù)類型的實(shí)數(shù)作為編碼個(gè)體的選擇[18]。每個(gè)參數(shù)即為編碼個(gè)體,不用對(duì)其解碼,簡化了算法過程。
適應(yīng)度函數(shù)是對(duì)個(gè)體進(jìn)行優(yōu)良判斷的定量準(zhǔn)則,以個(gè)體適應(yīng)度的大小來確定該個(gè)體在選擇階段被選中的概率[19]。適應(yīng)度值越大,被選為優(yōu)秀個(gè)體進(jìn)行遺傳的概率也越大,進(jìn)而引導(dǎo)程序向最優(yōu)解方向發(fā)展。常規(guī)適應(yīng)度函數(shù)的選取會(huì)直接采用待求函數(shù),通過待求函數(shù)對(duì)當(dāng)前用例的直接反應(yīng)來判斷個(gè)體的好壞。這種用待求解問題的標(biāo)準(zhǔn)來對(duì)個(gè)體適應(yīng)性進(jìn)行評(píng)估的方法,可以充分表達(dá)求解問題的需求。
系統(tǒng)服務(wù)模糊測(cè)試的目的是通過不斷發(fā)送異常參數(shù)來挖掘漏洞。觸發(fā)漏洞是最終目標(biāo),而觸發(fā)漏洞的異常參數(shù)就是待求的解。遺傳算法的選擇變異過程可以生成各種正?;蚍钦?shù),測(cè)試參數(shù)取值的多樣化往往能夠大概率發(fā)現(xiàn)漏洞。結(jié)合系統(tǒng)服務(wù)實(shí)際情況,可以將適應(yīng)度函數(shù)定義如下:
(1)
其中,n為測(cè)試樣例中參數(shù)個(gè)數(shù),該模型適用于單參數(shù)和多參數(shù)的場(chǎng)景。當(dāng)只有一個(gè)參數(shù)時(shí),適應(yīng)度函數(shù)就是一個(gè)二項(xiàng)分布函數(shù)。測(cè)試用例中有多個(gè)參數(shù)時(shí),每種類型參數(shù)的適應(yīng)度都為參數(shù)數(shù)目分之一,原因是每個(gè)類型的參數(shù)有可能是優(yōu)異個(gè)體或者是劣質(zhì)個(gè)體。在未觸發(fā)到異常之前,無法片面去評(píng)判某種類型參數(shù)的優(yōu)劣,所以在后續(xù)過程中要使用合適的選擇算子對(duì)個(gè)體做出挑選。如果測(cè)試用例觸發(fā)異常,遺傳概率則為0,即不對(duì)其進(jìn)行變異,此時(shí)需要對(duì)參數(shù)變進(jìn)行觀察,判斷參數(shù)應(yīng)該選擇拋棄還是觸發(fā)了漏洞,選擇拋棄則需要重新生成初始數(shù)據(jù),而觸發(fā)漏洞則說明已經(jīng)達(dá)到了測(cè)試效果,獲取到問題的最優(yōu)解。未觸發(fā)異常時(shí),測(cè)試用例適用度為1/n,則需要對(duì)測(cè)試用例進(jìn)行選擇交叉變異等操作,再次進(jìn)行測(cè)試。
2)選擇算子的選取。
選擇操作是使用選擇算子從前次測(cè)試群體中選擇優(yōu)秀個(gè)體,進(jìn)行交叉變異后遺傳給下一代的一種選擇機(jī)制,是遺傳變異過程中保優(yōu)去劣的重要一環(huán)。常用的選擇模式有輪盤賭選擇[20]、最佳個(gè)體保存、排序模型、聯(lián)賽選擇模型等[21]。每種模式都有其優(yōu)缺點(diǎn),對(duì)于單個(gè)參數(shù)的測(cè)試用例,在初始樣本未觸發(fā)到系統(tǒng)異?;蚵┒吹那闆r下,根據(jù)適應(yīng)度函數(shù)計(jì)算,其值為1。選擇算子模式為確定性選擇,即當(dāng)前測(cè)試用例個(gè)體U為優(yōu)異個(gè)體,將會(huì)遺傳給下一代進(jìn)行交叉變異。后續(xù)單個(gè)參數(shù)的用例同樣采取該選擇模式。
實(shí)際測(cè)試中,單個(gè)參數(shù)的測(cè)試用例較少,多為2個(gè)及以上參數(shù)。用例Group(U1,U2,U3,…,UN)初始群體經(jīng)過首輪測(cè)試,代入適應(yīng)度函數(shù)得出每個(gè)個(gè)體Ui的適應(yīng)度值均為1/n。在個(gè)體適應(yīng)度相等的情況下,如何選擇優(yōu)異個(gè)體對(duì)于后續(xù)用例的遺傳尤為重要。為了減小多維參數(shù)同時(shí)變異對(duì)遺傳選擇過程的干擾,在結(jié)合類型概率排序的前提下,提出一種基于組合的遺傳算子挑選模型。該模型首先對(duì)測(cè)試用例中的參數(shù)類型進(jìn)行一個(gè)變異優(yōu)先級(jí)排序,再根據(jù)組合公式挑選每次測(cè)試需要變異的個(gè)體。參數(shù)類型排序是根據(jù)其在服務(wù)接口中出現(xiàn)頻數(shù)及參數(shù)個(gè)體的可變異空間分配優(yōu)先級(jí)。參數(shù)個(gè)體有所屬的數(shù)據(jù)類型,每種參數(shù)類型有其特定的數(shù)據(jù)范圍。如布爾型只有false和true,字節(jié)型取值范圍為(-128,127),而整型、浮點(diǎn)型等類型的取值范圍就很大。為更快收斂到最優(yōu)解,挖掘到漏洞,將出現(xiàn)頻數(shù)高且變異空間取值范圍小的數(shù)據(jù)類型分配高優(yōu)先級(jí),而將需要構(gòu)造的參數(shù)類型的默認(rèn)為低優(yōu)先級(jí)。因此定義了類型變異選擇優(yōu)先級(jí)如表3所示,其中數(shù)值越小代表其被優(yōu)先挑選的概率越大。
表3 類型變異選擇優(yōu)先級(jí)表
測(cè)試用例中的參數(shù)首先根據(jù)類型變異選擇優(yōu)先級(jí)表對(duì)參數(shù)類型進(jìn)行一個(gè)排序,然后再根據(jù)選擇算子挑選算法選出該次需要變異的個(gè)體。挑選算法過程具體如下。
定義:
PriorityMap
Group(ParaType_U1,ParaType_U2,…,ParaType_Un)
PriorityList=[] //用來保存參數(shù)對(duì)應(yīng)的優(yōu)先級(jí)
ParaTypePriorityMap
M=Group.length //參數(shù)群體個(gè)數(shù)
算法:
輸入:當(dāng)前測(cè)試參數(shù)群體Group(ParaType…)
for(i=0;i { Priority=PriorityMap.get(Group[i]) if(PriorityList.exist(Priority))//判斷同類型 Priority=Priority+"-"+i; //同優(yōu)先級(jí)添加標(biāo)志 ParaTypePriorityMap.put(Group[i]:Priority) PriorityList.add(Priority) } PriorityList=Sort(PriorityList) //從小到大排序 for(j=1;j<=M;j++) {Combination_select(PriorityList,M,j)} Combination_select函數(shù)以組合公式為原型: 輸出:被挑選的優(yōu)先級(jí)數(shù)字序列[x]。 下面以輸入group(int,byte,long)為例: ①根據(jù)類型選擇優(yōu)先級(jí)映射表得到: ParaTypePriorityMap(int:6,byte:2,long:8) PriorityList[6,2,8] ②排序: PriorityList[2,6,8] 代入組合公式(1<=j<=3): Combination_select([2,6,8],3,j) ③當(dāng)j=1,輸出:[2],[6],[8] 當(dāng)j=2,輸出:[2,6],[2,8],[6,8] 當(dāng)j=3,輸出:[2,6,8] ④根據(jù)ParaTypePriorityMap可得: 第一次被選擇類型為byte 第二次被選擇類型為int … 第四次被選擇類型為int,byte … 第七次被選擇類型為int,byte,long 初始群體根據(jù)對(duì)應(yīng)的參數(shù)類型生成優(yōu)先級(jí)序列,在對(duì)應(yīng)過程中要注意種群中可能存在相同參數(shù)類型,可添加相應(yīng)標(biāo)志進(jìn)行區(qū)分。然后序列排序后代入組合公式函數(shù)進(jìn)行挑選。最后被挑選的優(yōu)先級(jí)序列再對(duì)照找到其對(duì)應(yīng)的數(shù)據(jù)類型。要注意的是該算法選擇的是多個(gè)參數(shù)中哪些類型的參數(shù)需要改變,并不影響測(cè)試模塊中數(shù)據(jù)的填充順序。在一組測(cè)試用例遺傳變異過程中,被選擇到的個(gè)體默認(rèn)是被選中的優(yōu)秀個(gè)體,即將對(duì)其進(jìn)行交叉變異操作,而用例中沒有被選中的個(gè)體則保持原值傳遞,直至次數(shù)達(dá)到或者觸發(fā)漏洞。此種遺傳算子挑選模型在一定程度上避免了組合爆炸帶來的混亂問題,也保證了優(yōu)秀個(gè)體的有效傳遞。 3)交叉變異操作。 參數(shù)用例的多樣性越好,觸發(fā)漏洞的幾率就越大。而交叉變異就是使不同個(gè)體向較為優(yōu)化的局部疊加,生成新個(gè)體的主要過程。作為被挑選的優(yōu)秀個(gè)體,需要對(duì)其進(jìn)行相應(yīng)的交叉變異操作。結(jié)合遺傳算法編碼方案的選取,為簡化算法和保留個(gè)體有效性,對(duì)個(gè)體不采取交叉操作,只對(duì)其進(jìn)行變異操作。常用的變異策略有隨機(jī)變異、邊界變異、多項(xiàng)式變異等[22]。結(jié)合模糊測(cè)試實(shí)際情況,參數(shù)個(gè)體都有不同的數(shù)據(jù)類型,所以根據(jù)參數(shù)所屬類型的差別也采取相應(yīng)的變異策略。對(duì)于int、float、long、double等常規(guī)類型參數(shù),變異算子如圖5所示。 圖5 變異算子選擇模型 數(shù)值根據(jù)[1,2,3,4,5]元素排列組合生成的序列執(zhí)行不同的操作,其中為保證生成的數(shù)據(jù)能發(fā)散到各個(gè)數(shù)據(jù)段,constant值也根據(jù)類型相應(yīng)變化賦值。該次變異后的數(shù)據(jù)會(huì)被保存作為下次的初始值輸入,保證數(shù)據(jù)有效性地傳遞。而對(duì)于int[]、float[]等數(shù)組類型的數(shù)據(jù),其中變異的不只是數(shù)據(jù),還有數(shù)組的長度。對(duì)于數(shù)據(jù)的填充,仍可以采用以上的常規(guī)類型的遺傳算子進(jìn)行生成。長度的控制則每次動(dòng)態(tài)生成,可以通過該測(cè)試次數(shù)對(duì)自定義的最大長度取余加1確定。 對(duì)于Binder、ComponentName等非常規(guī)數(shù)據(jù)類型,變異方式采用隨機(jī)變異。Binder是各種服務(wù)的句柄,可以通過反射得到。ComponentName類型的參數(shù),可以根據(jù)系統(tǒng)內(nèi)置的一些固定用法進(jìn)行構(gòu)造。而對(duì)于存在多個(gè)構(gòu)造函數(shù)的參數(shù)類,構(gòu)造函數(shù)的選取可以使用隨機(jī)變異,但構(gòu)造函數(shù)中常規(guī)類型參數(shù)的構(gòu)造仍采用圖5所示的變異算子進(jìn)行構(gòu)造填充。 4)終止條件。 ASFuzzer框架默認(rèn)下一代用例更優(yōu),即要對(duì)用例進(jìn)行遺傳變異操作。當(dāng)測(cè)試用例中的異常參數(shù)觸發(fā)漏洞,則可終止測(cè)試[23]。但大多數(shù)測(cè)試用例可以順利通過接口測(cè)試,對(duì)于這種情況,就需要對(duì)變異次數(shù)進(jìn)行一定的限制。對(duì)于單個(gè)參數(shù)的變異,次數(shù)區(qū)間建議設(shè)置在[300,500],而對(duì)于多個(gè)參數(shù)的變異,則主要是根據(jù)接口參數(shù)類型的不同組合進(jìn)行次數(shù)限制。每種不同的參數(shù)類型變異組合測(cè)試可設(shè)置為300次。而對(duì)于那些接口有權(quán)限檢測(cè)或者參數(shù)校驗(yàn)的情況,當(dāng)用例測(cè)試到一定次數(shù)即可停止測(cè)試,判定此接口安全。 ASFuzzer測(cè)試框架采用Java語言開發(fā),并將其安裝在不同系統(tǒng)的手機(jī)上進(jìn)行測(cè)試,包括谷歌原生Android系統(tǒng)及第三方定制系統(tǒng)。實(shí)驗(yàn)均采用真機(jī)測(cè)試,以保證結(jié)果的真實(shí)可靠。其中Nexus5x手機(jī)搭載谷歌原生系統(tǒng)版本分別為bullhead Android 6.0.0、bullhead Android 7.1.1和bullhead Android 8.1.0。Pixel手機(jī)搭載谷歌原生系統(tǒng)sailfish Android 9.0.0和sailfish Android 10.0.0。小米機(jī)型為MI3,系統(tǒng)為MIUI8 7.6.11|開發(fā)版。OPPO機(jī)型為OPPO-R9s-Plus,操作系統(tǒng)為ColorOS。 ASFuzzer共發(fā)現(xiàn)25個(gè)Android系統(tǒng)服務(wù)安全漏洞,漏洞行為主要有手機(jī)重啟、應(yīng)用拒絕服務(wù)、手機(jī)黑屏、系統(tǒng)應(yīng)用進(jìn)程停止運(yùn)行等。目前已將相關(guān)漏洞提交給廠家確認(rèn)。漏洞詳細(xì)信息如表4和表5所示。 表4 谷歌原生Android系統(tǒng)漏洞 表5 第三方定制系統(tǒng)漏洞 從實(shí)驗(yàn)結(jié)果分析來看,ASFuzzer框架挖掘到的漏洞數(shù)量在相同系統(tǒng)版本情況下,多于文獻(xiàn)[3]使用的常規(guī)模糊測(cè)試挖掘到的系統(tǒng)服務(wù)漏洞數(shù)目,并且在第三方廠家定制系統(tǒng)上測(cè)試也取得了一定的成果。遺傳算法變異生成高多樣化的測(cè)試用例,大大提高了觸發(fā)漏洞的可能性。通過分析產(chǎn)生異常的接口及其參數(shù),在25個(gè)漏洞中有19個(gè)是因?yàn)槎鄥?shù)組合變異所引起的漏洞,即只有當(dāng)特定數(shù)據(jù)被填充才會(huì)引發(fā)異常。實(shí)驗(yàn)結(jié)果說明基于遺傳算法的模糊測(cè)試在系統(tǒng)服務(wù)的漏洞挖掘中遠(yuǎn)優(yōu)于常規(guī)的模糊測(cè)試方法,具有一定的高效性與優(yōu)越性。 在遺傳算法挖掘策略上,文獻(xiàn)[13]在選擇算子階段采用隨機(jī)的方式對(duì)當(dāng)前種群中的個(gè)體進(jìn)行挑選。作為即將進(jìn)入下一輪的個(gè)體,隨機(jī)挑選可能會(huì)錯(cuò)失優(yōu)異個(gè)體,進(jìn)而誤導(dǎo)測(cè)試的方向,影響挖掘效率。而本文充分利用單個(gè)參數(shù)的可變異范圍及參數(shù)的數(shù)量關(guān)系,并結(jié)合排列組合的方式對(duì)遺傳算法過程中的選擇運(yùn)算進(jìn)行指導(dǎo),保證了優(yōu)秀個(gè)體的及時(shí)輸入,從而引導(dǎo)挖掘測(cè)試向高效的方向發(fā)展。 SystemServer系統(tǒng)進(jìn)程運(yùn)行著大量的基本服務(wù),單個(gè)服務(wù)引起的異常極易引起系統(tǒng)進(jìn)程的崩潰,從而影響到Android系統(tǒng)的穩(wěn)定。通過對(duì)服務(wù)端返回的reply信息以及系統(tǒng)日志等分析發(fā)現(xiàn),系統(tǒng)服務(wù)出現(xiàn)的安全異常主要體現(xiàn)在以下4個(gè)方面: 1)存在少量不合法參數(shù)異常。原因是有些參數(shù)類型無法構(gòu)造或者使用了null填充,無法通過底層目標(biāo)函數(shù)的參數(shù)校驗(yàn)。 2)出現(xiàn)較多安全異常。說明目標(biāo)函數(shù)對(duì)調(diào)用者的身份權(quán)限做了判斷,對(duì)接口增加了防護(hù)。 3)日志信息無明顯異常。說明參數(shù)通過了目標(biāo)函數(shù)的參數(shù)校驗(yàn)或權(quán)限判斷。此類接口默認(rèn)低權(quán)限可以調(diào)用,接口對(duì)外暴露,是漏洞挖掘的重點(diǎn)。 4)嚴(yán)重異常信息。如系統(tǒng)重啟、拒絕服務(wù)、系統(tǒng)應(yīng)用崩潰等,表明該接口存在嚴(yán)重漏洞。 綜合以上結(jié)果及漏洞成因分析,可以得出系統(tǒng)服務(wù)安全防護(hù)的3要素:參數(shù)校驗(yàn)、權(quán)限判斷、異常處理。做好以上3點(diǎn)可以在一定程度上加強(qiáng)Android系統(tǒng)服務(wù)的安全性。 本文在Binder與系統(tǒng)服務(wù)之間的通信基礎(chǔ)上設(shè)計(jì)了ASFuzzer系統(tǒng)服務(wù)漏洞挖掘工具。經(jīng)過遺傳算法對(duì)用例的持續(xù)優(yōu)化,使其生成更全面、更多樣化的用例去測(cè)試目標(biāo)函數(shù),進(jìn)而觸發(fā)漏洞。在不同系統(tǒng)上測(cè)試結(jié)果顯示,ASFuzzer測(cè)試框架可以有效地對(duì)系統(tǒng)服務(wù)進(jìn)行漏洞挖掘,進(jìn)而發(fā)現(xiàn)其中潛在的一些安全問題;同時(shí)也表明了該方案相比常規(guī)模糊測(cè)試挖掘方法效率的優(yōu)越性。但該工具仍存在一些不足,如對(duì)異常信息的記錄及分析不能做到完全自動(dòng)化,測(cè)試結(jié)果對(duì)遺傳算法的反饋處理不夠細(xì)膩等。這些不足之處都需要在未來對(duì)其進(jìn)行改進(jìn)和優(yōu)化,以便提高測(cè)試效率。4 實(shí)驗(yàn)結(jié)果與驗(yàn)證分析
4.1 實(shí)驗(yàn)環(huán)境
4.2 系統(tǒng)服務(wù)漏洞列表
4.3 挖掘能力分析
4.4 系統(tǒng)服務(wù)安全性分析
5 結(jié)束語