◎侯 楓 趙 倩
(三門峽職業(yè)技術(shù)學(xué)院 信息傳媒學(xué)院,河南 三門峽 472000)
Android應(yīng)用程序輸入接口,只提供靜態(tài)權(quán)限檢查保護機制,不進行輸入驗證。若防范措施不嚴密,容易導(dǎo)致混淆代理漏洞(Confused Deputy Attack)和拒絕服務(wù)漏洞。如何挖掘Android環(huán)境下輸入驗證漏洞是筆者主要討論的問題。
目前輸入驗證漏洞挖掘通過先驗知識,預(yù)定義某特定類型漏洞模式,通過模式匹配在執(zhí)行代碼上進行漏洞挖掘[1]。挖掘輸入驗證漏洞難點是難以給出漏洞通用模式。為更好檢測與程序邏輯相關(guān)漏洞,破解難點,筆者提出針對Android應(yīng)用輸入驗證漏洞基于源代碼分析靜態(tài)挖掘方案。方案使用后向程序切片算法在控制流圖上提取事務(wù)切片和約束切片,通過頻繁模式挖掘獲得切片級隱式安全規(guī)范,驗證規(guī)范并將違規(guī)現(xiàn)象報告為可疑漏洞,根據(jù)收集的路徑約束條件推斷輸入取值范圍,自動化生成測試用例并在虛擬機上半自動的驗證漏洞報告。
傳統(tǒng)的漏洞挖掘方案都是經(jīng)過大量漏洞細節(jié)的人工分析,建立一個固定的漏洞模型,然后從代碼實現(xiàn)中查找符合該漏洞模型的代碼行為。由于無法對輸入驗證漏洞用一個統(tǒng)一標準漏洞模型描述,因此“漏洞建模-模型檢測”的檢測模式不甚理想。由于Android功能設(shè)計中代碼存在大量重復(fù)片段,抽取重復(fù)片段的行為模式得到該程序應(yīng)該遵守的規(guī)范,不符合規(guī)范行為即為可疑漏洞[2]。為能提取出此類行為模式,需對輸入驗證漏洞進行形式化的建模。
定義事務(wù)。事務(wù)(Transaction)是包含一個核心語句及其所有數(shù)據(jù)依賴語句的語句集合。從定義可以看出,事務(wù)具有原子性,整個事務(wù)是一個不可分割的功能片段,所有語句一起完成某個特定的功能。一個事務(wù)通常用最后一條語句明確執(zhí)行某個功能,其他語句只是為該中心語句準備所需的數(shù)據(jù)。
事務(wù)通過一個四元組T<s,Ds,CS,Dv>定義,其中s是整個事務(wù)的核心語句,Ds是事務(wù)所有依賴語句集合,CS是事務(wù)所有約束集合,Dv是事務(wù)所有依賴變量集合。
形式化定義如下,其中REF(si)是語句si所有依賴變量,DEF(si)是語句si中被賦值變量:
●s=o.fun(p1,p2,...,pn)
●Ds={s1,s2,...,sn},s1,s2,...,sn是順序執(zhí)行的語句,sn就是核心功能語句 s,則對于(i∈[2,n]),存在 sj,j∈[1,i),DEF(sj)F(si)
●CS={cs1,cs2,...,csn},其中csi是事務(wù)T的約束(隨后定義)
●Dv={v|v∈{o,p1,p2,...,pn}ⅴv∈REF(si),si∈Ds}
定義約束。約束(Constraint)是一個事務(wù)可以被順利執(zhí)行所需滿足的一個路徑條件語句,代表著對這個事務(wù)執(zhí)行過程中變量或者環(huán)境的驗證行為。一個事務(wù)通常會有多個約束,只有這些約束都得到滿足的時候,一個事務(wù)才能執(zhí)行完成。一個條件語句是一個事務(wù)約束的充要條件,是該約束在控制流圖上到達該事務(wù)路徑上的分支節(jié)點。
約束通過一個三元組T<s,Ds,Dv>定義,其中s是整個事務(wù)核心語句,Ds是事務(wù)所有依賴語句集合,Dv是事務(wù)所有依賴變量集合。形式化定義如下:
●s=o1.fun1(p1,p2,...,pn)relop o2.fun2(q1,q2,...,qn),relop是關(guān)系運算符
●Ds={s1,s2,...,sn},s1,s2,...sn是順序執(zhí)行的語句,sn就是約束條件語句s,則對于si(i∈[2,n]),存在sj,j∈[1,i),DEF(sj)REF(si)
●Dv={v|v∈{o,p1,p2,...,pn}ⅴ v∈REF(si),si∈ Ds}
定義輸入驗證漏洞。輸入驗證漏洞是一個事務(wù)缺少必要約束而導(dǎo)致。給定事務(wù)T<s,Ds,CS,Dv>和安全規(guī)范集合SR{s|sis necessary constraint},T存在輸入驗證漏洞。當且僅當:
從定義知,挖掘輸入驗證漏洞關(guān)鍵在于如何提取安全規(guī)范集合SR,及判定一個約束對于一個事務(wù)是否是必要的。為能從源代碼中提取出事務(wù)和約束,使用后向程序切片技術(shù)(backward slicing)[3]細分程序邏輯,從某個程序點P出發(fā),逆向遍歷重構(gòu)控制流圖并收集所有和程序點P存在數(shù)據(jù)依賴關(guān)系的語句和分支謂詞,進而提取事務(wù)切片和約束切片。
通過預(yù)處理、程序切片、漏洞檢測及漏洞驗證設(shè)計基于隱式模式掘的漏洞挖掘流程。如圖1所示。
對Java源代碼進行解析,獲取抽象語法樹 (Abstract Syntax Tree)和控制流圖、系統(tǒng)依賴圖(System Dependence Graph)[4]。為方便精確分析數(shù)據(jù)流,將復(fù)雜語句變成三地址模式靜態(tài)單賦值 (Static Single-Assignment)語句。每一條靜態(tài)單賦值語句只給一個變量賦值一次,根據(jù)manifest.xml文件重構(gòu)控制流圖。
圖1 基于隱式模式的漏洞挖掘流程
利用后向切片技術(shù),將某一安全敏感語句識別為切片中心語句,以它為起點,收集數(shù)據(jù)依賴語句作為事務(wù)切片。將路徑分支語句識別為切片中心語句,通過程序切片技術(shù)獲得約束切片。
用事務(wù)切片和切片代表程序邏輯的抽象,在切片級別進行漏洞檢測。首先,依據(jù)中心語句不同將事務(wù)切片進行分類;提取同一類事務(wù)中出現(xiàn)頻繁的約束切片為隱式安全規(guī)范,并應(yīng)用到該類事務(wù)中,不滿足規(guī)范切片識別為可疑安全漏洞。
通過半自動漏洞驗證模塊對原始漏洞報告進行驗證。在一臺Android虛擬機上驗證簡單輸入漏洞;對于復(fù)雜漏洞,輸入求解過程結(jié)果不理想,但一定程度上能輔助人工分析并生成最終報告,報告中包含受影響的切片和修復(fù)方案。
在系統(tǒng)設(shè)計基礎(chǔ)上實現(xiàn)基于隱式模式的漏洞挖掘各個模塊細節(jié)。
在實現(xiàn)系統(tǒng)設(shè)計中預(yù)處理功能外,需增加針對異常拋出Assert語句和Service Hook API的處理,以方便收集更多種類約束。
Assert語句。Java語言中Assert語句是斷言式語句,幫助開發(fā)者動態(tài)驗證特定程序點是否滿足預(yù)設(shè)條件[5]。若不滿足,Assert語句拋出AssertionError異常,Catch語句捕獲異常,否則控制流直接結(jié)束函數(shù)或程序。為處理該情況,將Assert語句條件表達式轉(zhuǎn)變?yōu)镮F語句,使其成為后續(xù)所有語句的隱式約束。
Service Hook API。Service HookAPI用于動態(tài)細粒度驗證訪問者權(quán)限,用于保護某個Service組件方法。在調(diào)用時檢查調(diào)用者權(quán)限,權(quán)限不夠則拋出異常。Service Hook作為靜態(tài)權(quán)限機制補充,需將其識別為約束,處理方法同Assert語句。
程序切片采用的提取算法,能同時提取事務(wù)切片和約束切片。算法思路是從函數(shù)最后一條語句(通常是return語句)開始,逆向遍歷控制流圖,將所有安全敏感函數(shù)調(diào)用語句識別為切片中心語句,利用后向切片算法提取事務(wù)切片。從安全敏感函數(shù)調(diào)用語句開始,逆向遍歷控制流圖,收集所有數(shù)據(jù)依賴,直到控制流圖入口點止。獲得包含一個切片中心語句和所有數(shù)據(jù)依賴語句的完整事務(wù)切片。
帶著這樣的問題,我梳理了自己30年的語文教學(xué),研究了于漪、錢夢龍等一大批語文教學(xué)名家的教育實踐,尤其是他們的課堂教學(xué),驚喜地發(fā)現(xiàn):新課改從理念到實踐,不是憑空而來的,也不像有些人所理解的是從西方引進的(其他學(xué)科或許可以引進,但母語教學(xué)是不能引進的),而是在繼承中發(fā)展的。新課程的很多理念在這一批教育名家的課堂上早就有了充分的體現(xiàn)。
切片示例:圖2是從函數(shù)stk.BootCompletedReceiver.onReceive()中提取事務(wù)切片和所有相關(guān)約束切片。第4條語句是敏感API context.startService(),該API啟動組件間通信service組件。本示例列出該事務(wù)切片包含的1條約束,該約束檢查action變量是否等于某個確定值,而其數(shù)據(jù)依賴關(guān)系最后都指向輸入函數(shù)參數(shù)(即 Intent)。
圖2 事務(wù)切片和約束切片示例
從程序切片中提取隱式安全規(guī)范是破解預(yù)先不能提供統(tǒng)一漏洞模式和安全規(guī)范的有效算法。通過事務(wù)分類、提取隱式安全規(guī)范和驗證安全規(guī)范等流程將提取事務(wù)切片按切片中心語句是否相等劃分為不同類別,頻繁挖掘各事務(wù)類別所有約束切片,在滿足安全規(guī)范的事務(wù)類別中檢測可疑違規(guī)行為。如果某事務(wù)切片缺少某相關(guān)聯(lián)安全規(guī)范,認為該事務(wù)切片存在可疑漏洞。
3.3.1 事務(wù)分類
相似事務(wù)具有相似約束,先利用切片中心語句的相等性對事務(wù)切片進行分類。給定兩個事務(wù)切片中心語句o_1.fun_1(p_1,p_2,…,p_n)和o_2.fun_2(q_1,q_2,…,q_n),兩個中心語句相等條件是o1和o2實例化自同一個類或繼承自同一個父類的兩個子類,且兩個函數(shù)名相等,參數(shù)也相同。
形式化定義如下:給定o1的類O1,o2的類O2,符號“<”代表類的繼承關(guān)系,px的類Px和qx的類Qx,那么
這里將Android組件間通信API族(startActivity(),startService(),sendBroadcast()等)統(tǒng)一識別為相等切片中心語句[6]。
3.3.2 提取隱式安全規(guī)范
抽取該事務(wù)類別所有約束切片,匯總到約束切片集合中,提取多于N次出現(xiàn)的約束切片作為安全規(guī)范。采用約束切片中心語句相等性代表約束切片相等性,給定兩個約束切片中心語句o1.fun1(...)relop o2.fun2(...)和 o1’.xfun1’(...)relop’o2’.fun2’(...)其中 relop 是關(guān)系運算符(<,<=,=,<>,>,>=等),o.fun(...)為 Null,或者 relop和o2.fun2(...)均為空,這樣所有約束切片語句可化成如上形式。
注意,為盡量收集更多約束信息,約束切片出現(xiàn)頻數(shù)N的閾值設(shè)為1,會導(dǎo)致一定程度提高誤報率,若提高閾值會降低誤報率,但會升高漏報率。綜合考慮選擇閾值為1。
利用已提取安全規(guī)范驗證事務(wù)分類中規(guī)范并檢測可疑違規(guī)行為[7]。如果一個事務(wù)和一個安全規(guī)范存在相關(guān)性,該事務(wù)約束切片不包含該安全規(guī)范,那么該事務(wù)由于缺失該安全規(guī)范存在安全漏洞。檢測事務(wù)和安全規(guī)范相關(guān)性的判定標準是:變量數(shù)據(jù)類型是判定兩個依賴變量集相等性的根據(jù),當一個事務(wù)依賴變量集(Dependence Variables)包含提取安全規(guī)范的依賴變量集時,認為該事務(wù)和安全規(guī)范存在相關(guān)性。如一個事務(wù)依賴變量集為 {Intent,Message,SmsMessage,Context},安全規(guī)范依賴變量集為{Context,Intent,String,int},去掉基礎(chǔ)類型后,由于{Context,Intent}?{Intent,Message,SmsMessage,Context},那么就認為該安全規(guī)范與該事務(wù)是相關(guān)的。
由于輸入驗證漏洞敏感API不一定是系統(tǒng)API,對它調(diào)用不經(jīng)過ActivityManagerService仲裁,所以不能完備監(jiān)控此類調(diào)用。因此,設(shè)計一個自動化漏洞驗證模塊,選擇使用靜態(tài)插樁方法監(jiān)控API調(diào)用。如圖3所示,使用Soot修改目標APK二進制代碼,插入一條新語句在被關(guān)注API調(diào)用語句前,記錄API調(diào)用信息和上下文信息到系統(tǒng)日志中,重新打包APK并安裝到Android虛擬機或物理機中。
同時使用簡單約束求解器推斷輸入,利用代碼發(fā)送到目標Android機器中,再使用logcat監(jiān)控系統(tǒng)日志,發(fā)現(xiàn)API調(diào)用信息或者app崩潰信息及時記錄,并輸出驗證報告。如果監(jiān)控到預(yù)期行為,將該可疑漏洞標記為“Confirmed Vul”,否則標記為“False Alarm”。如果不存在可執(zhí)行文件(.apk)或漏洞輸入條件無法求得,那么將其標記為“Unconfirmed Alarm”。
圖3 基于靜態(tài)插樁的漏洞驗證
選取packages/apps和packages/providers中應(yīng)用源碼在不同版本Android原生系統(tǒng)進行測試,測試集詳情見表1。
表1 測試集匯總
在App上應(yīng)用算法得到相應(yīng)可疑漏洞報告,通過人工審核源代碼并編寫利用代碼的方式來驗證這些漏洞。驗證結(jié)果見表2。其中列“Apps”是存在漏洞app包名,列“Vulnerable Component”是存在該漏洞組件名,×表示該版本不存在App(NFC功能在Android2.3之后才引入),表示無漏洞。
實驗表明,設(shè)計工具共檢測到36個未公開輸入驗證漏洞,均為拒絕服務(wù)漏洞,這些漏洞通過合適場景能造成嚴重破壞;Android版本迭代更新若干年,拒絕服務(wù)漏洞數(shù)量細微變化造成的損失并沒有引起程序員足夠重視。
表2 檢測到的輸入驗證漏洞
為檢測和程序邏輯相關(guān)、難以提取統(tǒng)一模式輸入驗證漏洞,本文提出基于隱式模式挖掘,用于發(fā)現(xiàn)源代碼中隱含安全規(guī)范并檢測漏洞。該技術(shù)應(yīng)用后向程序切片技術(shù)提取程序邏輯,抽取獨立功能代碼片段為一個事務(wù)切片,抽取一個路徑約束條件和相關(guān)語句代碼片段為一個約束切片,在切片級別上進行事務(wù)切片分類,在類別內(nèi)采用頻繁模式挖掘,提取隱式安全規(guī)范檢測漏洞。在Android2.2、4.0.3、4.4.2和5.0等版本上實現(xiàn)一個原型系統(tǒng),檢測出36個拒絕服務(wù)漏洞,充分驗證該方案不僅能從源代碼中有效提取隱式安全規(guī)范并挖掘漏洞,同時通過自動化樣本生成和自動化驗證顯著降低誤報率。