文/張煜龍 陳越 包沉浮 夏良釗 鄭龍日 盧永強(qiáng) 韋韜
基于自適應(yīng)熱補(bǔ)丁的Android內(nèi)核漏洞生態(tài)修復(fù)方案
文/張煜龍 陳越包沉浮夏良釗鄭龍日盧永強(qiáng) 韋韜
學(xué)術(shù)專欄
Android內(nèi)核漏洞嚴(yán)重影響了Android平臺(tái)的安全。一旦內(nèi)核被攻破,所有依賴內(nèi)核完整性的安全機(jī)制都岌岌可危(比如加密、進(jìn)程隔離、支付、指紋驗(yàn)證等)。作為Android平臺(tái)最后的防線,TrustZone也會(huì)受到威脅,因?yàn)閮?nèi)核可以從很多被信任的接口向TrustZone發(fā)起攻擊。因此,理想情況下Android生態(tài)圈應(yīng)該及時(shí)消滅內(nèi)核漏洞。然而從Google的Android Security Bulletin上看,Android內(nèi)核漏洞的數(shù)量呈飛快上漲的趨勢(shì)(圖1所示)。雖然這代表著人們對(duì)內(nèi)核安全的投入逐漸增大,但與此同時(shí)這些漏洞一旦公諸于眾,在很長(zhǎng)一段時(shí)間都難以得到修復(fù),導(dǎo)致越來(lái)越多的可以公開(kāi)利用的漏洞變成了黑產(chǎn)手中的利器。縱觀近期幾起影響全世界的重大惡意malware事件[1-4],它們都攜帶了root工具,并且root的方法不是源自公開(kāi)的PoC,就是直接重用了一些一鍵root工具的庫(kù)。
人們經(jīng)常宣稱“Android容易被攻擊”或者“Android不如蘋果安全”。但是,表1列出了幾乎同時(shí)期iOS和Android內(nèi)核漏洞數(shù)量的比較,不難發(fā)現(xiàn)Android漏洞公布的頻率甚至不如iOS多。雖然漏洞和漏洞并不能直接拿來(lái)比較(因?yàn)槲:Τ潭炔灰欢ㄒ粯樱?,但至少這可以提供一個(gè)參考基準(zhǔn)——至少蘋果不是生來(lái)就安全的,而且也需要定期修復(fù)大量的內(nèi)核漏洞。只是因?yàn)閕OS修補(bǔ)漏洞比較全面和及時(shí),讓人感覺(jué)它非?!鞍踩?。同樣地,“Android不安全”并不是僅僅因?yàn)槁┒搭l發(fā),更重要的還是不能像iOS這樣及時(shí)地修復(fù)問(wèn)題。
第一,Android的產(chǎn)業(yè)鏈過(guò)長(zhǎng):Android生態(tài)系統(tǒng)產(chǎn)業(yè)鏈非常長(zhǎng),從硬件廠商,到Google,到手機(jī)廠商,再到運(yùn)營(yíng)商。每一個(gè)環(huán)節(jié)都有自己的開(kāi)發(fā)、質(zhì)控、驗(yàn)證等復(fù)雜流程,有時(shí)候還會(huì)相互沖突。這樣要消耗大量的時(shí)間和人力,而且有時(shí)甚至導(dǎo)致安全補(bǔ)丁無(wú)法下發(fā)給用戶。這個(gè)冗長(zhǎng)的修補(bǔ)鏈條如圖2所示。
表1
第二,Android系統(tǒng)碎片化過(guò)于嚴(yán)重:Android系統(tǒng)的碎片化是指世界上所有Android用戶實(shí)際使用的Android版本、配置、驅(qū)動(dòng)等等有著非常顯著的差異。Android系統(tǒng)碎片化已經(jīng)成為了業(yè)界共識(shí),由于系統(tǒng)的開(kāi)源性,用戶、開(kāi)發(fā)者、OEM廠商、運(yùn)營(yíng)商都可以按照自己的想法進(jìn)行改造,這種“碎片化”的程度異常嚴(yán)重。在這種情況下,大多數(shù)手機(jī)設(shè)備廠商已經(jīng)失去了為所有用戶使用的Android系統(tǒng)提供安全補(bǔ)丁的能力。圖3所示為繁多的Android品牌和機(jī)型。
圖1
圖2
根據(jù)Google官方發(fā)布于2016年7月的統(tǒng)計(jì)[6]:
1.Lollipop (Android 5.0) 發(fā)布于November 2014, 但是仍然有55% 的設(shè)備低于該版本
2.Google已經(jīng)停止為低于4.4版本的Android提供補(bǔ)丁,但仍有23%的設(shè)備低于該版本
而在中國(guó),由于對(duì)Google的訪問(wèn)被阻隔,這一問(wèn)題更加嚴(yán)重。通過(guò)隨機(jī)采樣大約200萬(wàn)裝有Baidu App的設(shè)備的手機(jī),我們發(fā)現(xiàn):
1.80% 的設(shè)備低于Android 5.0
2.42% 的設(shè)備低于Android 4.4
第三,生態(tài)職能不匹配:其實(shí)最容易推進(jìn)修復(fù)的是手機(jī)廠商,但大部分手機(jī)廠商自身的碎片化現(xiàn)象非常嚴(yán)重,導(dǎo)致了手機(jī)廠商沒(méi)有足夠的資源和精力去修復(fù)漏洞。而對(duì)于安全廠商來(lái)講,修復(fù)漏洞也是一件很尷尬的事情。在正常情況下,安全廠商是沒(méi)有系統(tǒng)授權(quán)的,除非先進(jìn)行root。即使root,安全廠商仍然要面臨不同手機(jī)品牌更加嚴(yán)重的碎片化挑戰(zhàn)。
案例分析
具體看3個(gè)著名的能被用來(lái)進(jìn)行跨平臺(tái)root的漏洞:第一個(gè)是CVE-2014-3153(Towelroot),公開(kāi)和修補(bǔ)時(shí)間為June 3, 2014[7];第二個(gè)是CVE-2015-3636(Ping Pong Root),公開(kāi)和修補(bǔ)時(shí)間為 September 9, 2015[8];第三個(gè)是CVE-2015-1805,公開(kāi)時(shí)間為April 3, 2014[9],但直到March 18, 2016才在Android平臺(tái)上修復(fù)[10]。圖4 所示為這三個(gè)漏洞距今(2016年7月)的時(shí)間跨度。其中最短的也達(dá)到了120天。
圖5 所示為這三個(gè)漏洞在裝有百度App的手機(jī)上的隨機(jī)采樣結(jié)果??梢?jiàn)雖然這么長(zhǎng)時(shí)間過(guò)去了,仍然有非常多的設(shè)備沒(méi)有得到漏洞修復(fù)。
AdaptKpatch: 自適應(yīng)內(nèi)核熱修補(bǔ)框架
如何解決Android漏洞得不到及時(shí)修補(bǔ)的問(wèn)題?對(duì)于跳過(guò)冗長(zhǎng)補(bǔ)丁鏈這個(gè)問(wèn)題,學(xué)術(shù)界工業(yè)界已經(jīng)給出了一些方案,比如kpatch[11], ksplice[12], kGraft[13], Linux upstream的livepatch[14],但是這些方案并沒(méi)有解決碎片化和能力失配的問(wèn)題。更本質(zhì)地說(shuō),這些方案都依賴源碼,對(duì)于沒(méi)有源碼的第三方不適用,更遑論補(bǔ)丁的廣泛適配。因此在第七屆HITB 會(huì)議上[15], 我們提出了內(nèi)核自適配修補(bǔ)的方案,稱作AdaptKpatch。其大致流程如圖6所示。
簡(jiǎn)單來(lái)說(shuō),該框架在手機(jī)上探測(cè)存在的內(nèi)核漏洞,向用戶征詢是否修復(fù)。得到允許后,該框架root手機(jī)并收集必要的信息,包括kernel versions, symbol addresses, symbol CRCs等。取決于設(shè)備是否提供insmod或者(k)mem 設(shè)備,框架會(huì)下載對(duì)應(yīng)的模板進(jìn)行數(shù)據(jù)結(jié)構(gòu)填充和symbol解析,并視情況對(duì)內(nèi)核的一些動(dòng)態(tài)校驗(yàn)機(jī)制進(jìn)行放寬。這些步驟完成后即完成補(bǔ)丁模板的適配,所生成的補(bǔ)丁即可插入該設(shè)備的內(nèi)核執(zhí)行修補(bǔ)操作。具體的修補(bǔ)操作和其他熱修補(bǔ)方案無(wú)異,比如函數(shù)替換、調(diào)用替換、原地修補(bǔ)等,此處不再贅述。 注意該框架只是熱修復(fù),因此每次重啟都要重新加載熱補(bǔ)丁。如果某次啟動(dòng)發(fā)現(xiàn)前次啟動(dòng)因?yàn)闊嵫a(bǔ)丁而出現(xiàn)崩潰,則放棄加載熱補(bǔ)丁回滾到正常啟動(dòng)。
圖3
圖4
圖5
圖6
如果手機(jī)廠商愿意和第三方協(xié)作修復(fù)時(shí),該框架可以最大化發(fā)揮效益。廠商不再需要花資源和精力修補(bǔ)漏洞,只需要提供預(yù)制的內(nèi)核修補(bǔ)機(jī)制/能力,而安全廠商不需要再root手機(jī)和探測(cè)漏洞,可以專注在修補(bǔ)漏洞上。這一合作模式如圖7所示?;谶@一合作聯(lián)盟,可有如下安全機(jī)制保證補(bǔ)丁的安全。
1.廠商資質(zhì)校驗(yàn):只有有能力和名聲好的廠商方可進(jìn)入合作聯(lián)盟,各廠商所發(fā)補(bǔ)丁需簽名驗(yàn)證;
2.補(bǔ)丁審計(jì):補(bǔ)丁發(fā)放前需要經(jīng)過(guò)聯(lián)盟里別的廠商進(jìn)行安全審計(jì),防止引入新的漏洞或者后門;
3.評(píng)價(jià)排名:類似于App Store,用戶可以對(duì)某個(gè)補(bǔ)丁進(jìn)行穩(wěn)定性等方面的評(píng)價(jià)。其他用戶可以根據(jù)補(bǔ)丁的既有評(píng)價(jià)選擇打還是不打。
設(shè)計(jì)原理
AdaptKpatch已經(jīng)能很好地解決Android內(nèi)核漏洞長(zhǎng)期得不到修復(fù)的問(wèn)題了,但補(bǔ)丁仍然需要通過(guò)審計(jì)才能保證安全。因此我們還提出了另一個(gè)方案:LuaKpatch。其原理是用類型安全(type-safe)的動(dòng)態(tài)語(yǔ)言引擎(比如Lua)來(lái)執(zhí)行補(bǔ)丁。這樣一來(lái)補(bǔ)丁靈活易維護(hù),同時(shí)其執(zhí)行可以嚴(yán)格控制在引擎所允許的范圍內(nèi),也不擔(dān)心因?yàn)橐绯?、空指針引用等?wèn)題被攻擊劫持。
圖7
圖8
圖9
圖8 所示為絕大部分kernel漏洞攻擊的原理。一般而言攻擊者都需要灌入惡意的輸入來(lái)實(shí)現(xiàn)控制流劫持。因此LuaKpatch只需要在函數(shù)入口和函數(shù)中讀數(shù)據(jù)的位置插入檢查即可,不需要給予補(bǔ)丁任意hook的能力。
具體來(lái)說(shuō),我們有如下限制:
1.補(bǔ)丁可以hook函數(shù)入口,檢查參數(shù)和環(huán)境。
2.補(bǔ)丁也可以hook函數(shù)中的調(diào)用,前提是該調(diào)用返回的是狀態(tài)值(下文只有條件依賴),而不是指針等有數(shù)值依賴的返回值(copy_from_user滿足這一條件,返回是成功或失敗的狀態(tài)值)。
3.補(bǔ)丁可以任意讀,但不可寫,更不能發(fā)送數(shù)據(jù)出去。
4.補(bǔ)丁完成條件判斷后,可返回正?;虍惓?。這樣當(dāng)遇到攻擊輸入時(shí),內(nèi)核隨后的執(zhí)行不會(huì)觸及會(huì)被exploit的代碼。
為了更直觀地理解,圖9給出了一個(gè)具體的例子。fun調(diào)用了foo 和bar。其中fun的入口是允許被hook的,fun中foo的調(diào)用前和調(diào)用后也是允許被hook的,因?yàn)閒oo返回值只有條件依賴,而bar是不能被hook的,因?yàn)橄挛漠a(chǎn)生了數(shù)值依賴(其中一個(gè)域被用作函數(shù)指針進(jìn)行調(diào)用)。這樣一來(lái),攻擊者即使控制了補(bǔ)丁,也沒(méi)法通過(guò)返回惡意數(shù)值來(lái)實(shí)現(xiàn)任意代碼執(zhí)行。
我們?yōu)榉祷刂抵挥袟l件依賴的函數(shù)生成了一個(gè)白名單,對(duì)于一個(gè)目標(biāo)函數(shù),其調(diào)用只有在落在這個(gè)集合里時(shí)才能被hook檢查。而且注意hook發(fā)生在目標(biāo)函數(shù)調(diào)用處,而不是被調(diào)用函數(shù)的入口和返回處。我們稱能在函數(shù)口作檢查即可修復(fù)的漏洞為Type I vulnerabilities,而如果還需要在函數(shù)體內(nèi)對(duì)調(diào)用做hook檢查的,則稱為Type II vulnerabilities。稍后我們會(huì)給出兩種漏洞的數(shù)目。
圖10
表2
圖11
我們基于Lua實(shí)現(xiàn)了LuaKpatch,為了將Lua集成在內(nèi)核里,很多改變借鑒了lunatik-ng[16]. 比如數(shù)值應(yīng)該修改為整型而非浮點(diǎn)型。LuaKpatch的代碼大約1萬(wàn)1千行,其中核心的與修補(bǔ)有關(guān)的代碼大概600行。編譯后LuaKpatch模塊大小為800KB。廠商可以提前將這一模塊集成于內(nèi)核里,或者可以借用AdaptKpatch里所介紹的內(nèi)核模塊自適應(yīng)加載方法,后天由第三方root手機(jī)后插入內(nèi)核。
LuaKpatch為L(zhǎng)ua形式的內(nèi)核補(bǔ)丁提供了如下接口:符號(hào)搜索、hook(在指定位置插入trampoline,保存現(xiàn)場(chǎng)并調(diào)用Lua補(bǔ)丁的handler進(jìn)行判定,然后回到指定位置的下一指令)、內(nèi)存讀取、thread信息獲取。 圖10 為利用LuaKpatch修補(bǔ)Towelroot漏洞的實(shí)例。
有效性分析
如表2所示,近年幾乎有代表性的能用來(lái)root手機(jī)的內(nèi)核漏洞LuaKpatch都能修補(bǔ)。前面提到的能在函數(shù)口作檢查即可修復(fù)的漏洞為Type I vulnerabilities,而如果還需要在函數(shù)體內(nèi)對(duì)調(diào)用做hook檢查的,則稱為Type II vulnerabilities。圖11提供了這兩類漏洞的比例,大部分漏洞還是可以簡(jiǎn)單地通過(guò)在函數(shù)口進(jìn)行檢查來(lái)修補(bǔ)的。萬(wàn)一遇到LuaKpatch不能修補(bǔ)的漏洞,可以回滾到AdaptKpatch方案進(jìn)行修補(bǔ)。
性能測(cè)試
我們用CF-Bench[17]在裝有Android 4.4的Nexus 5 上測(cè)了四種情況:不打補(bǔ)丁,用LuaKpatch修補(bǔ)Towelroot,用LuaKpatch修補(bǔ)Ping Pong Root,用LuaKpatch修補(bǔ)二者。 結(jié)果如圖12 所示——LuaKpatch完全沒(méi)有帶來(lái)任何性能損耗。這是預(yù)料之中的,因?yàn)樘釞?quán)內(nèi)核漏洞往往出現(xiàn)在平時(shí)無(wú)法觸及的執(zhí)行路徑上,修補(bǔ)后并不對(duì)正常執(zhí)行產(chǎn)生影響。
圖12
圖13
圖14
盡管如此,我們還是想知道一旦被觸及,LuaKpatch的開(kāi)銷是多少。因此我們測(cè)試了chmod 系統(tǒng)調(diào)用的原始執(zhí)行時(shí)間、打上補(bǔ)丁但是補(bǔ)丁直接return的執(zhí)行時(shí)間(相當(dāng)于只是現(xiàn)場(chǎng)保存恢復(fù)和Lua進(jìn)出的開(kāi)銷)、打上補(bǔ)丁且補(bǔ)丁做一次條件判斷的執(zhí)行時(shí)間、打上補(bǔ)丁且補(bǔ)丁做一次內(nèi)存地址讀的執(zhí)行時(shí)間、打上補(bǔ)丁且補(bǔ)丁做一些列綜合操作(變量操作、內(nèi)存讀、條件判斷等,模擬一個(gè)比Towelroot和Ping Pong Root補(bǔ)丁更復(fù)雜的補(bǔ)丁的操作)的執(zhí)行時(shí)間,其結(jié)果如圖13所示??梢?jiàn)即使在復(fù)雜補(bǔ)丁的執(zhí)行下,也只多了3.74微秒的開(kāi)銷。這僅僅是chmod正常執(zhí)行的4%。
基本上,在我們的測(cè)試?yán)?,LuaKpatch補(bǔ)丁都能在5微秒的開(kāi)銷里完成任務(wù)。未來(lái)會(huì)把LuaKpatch的引擎換成LuaJIT[19],性能會(huì)得到進(jìn)一步提升。
基于本文所述AdaptKpatch和LuaKpatch技術(shù),Android修補(bǔ)流程可以改進(jìn)成如圖14所示。對(duì)于非常嚴(yán)重的問(wèn)題、需要幾天內(nèi)推出補(bǔ)丁的,可以用LuaKpatch;對(duì)于LuaKpatch不能解決的問(wèn)題,可以經(jīng)過(guò)補(bǔ)丁審計(jì)后用AdaptKpatch方案推出;最終冷補(bǔ)丁可以永久性地修補(bǔ)相應(yīng)問(wèn)題?;谶@一流程,Android內(nèi)核漏洞長(zhǎng)期難以被修復(fù)的問(wèn)題可以得到妥善解決。
我們呼吁Android生態(tài)圈建立一個(gè)開(kāi)放協(xié)作的聯(lián)盟,包括手機(jī)廠商、安全廠商和其他Android社區(qū)的成員。這個(gè)聯(lián)盟將具有非常重要的意義:
一是漏洞越來(lái)越多也越來(lái)越復(fù)雜,在LuaKpatch和AdaptKpatch提供的和作平臺(tái)上,大家可以分擔(dān)修補(bǔ)的難題,共享其成;
二是對(duì)于AdaptKpatch的場(chǎng)景,越多的參與者意味著更多更安全的補(bǔ)丁審計(jì);
三是整個(gè)Android生態(tài)圈應(yīng)該一起將這個(gè)熱修補(bǔ)流程維護(hù)成統(tǒng)一的標(biāo)準(zhǔn),防止在當(dāng)前設(shè)備碎片化之上又引入了修補(bǔ)方案的碎片化,導(dǎo)致最終還是各方分散力量修補(bǔ)漏洞、難以規(guī)模化有效地解決問(wèn)題。
[1] http://www.cmcm.com/blog/en/security/2015-09-18/799. html
[2] https://www.fireeye.com/blog/threat-research/2015/10/ kemoge_another_mobi.html
[3] https://www.bluecoat.com/security-blog/2016-04-25/ android-exploit-delivers-dogspectus-ransomware
[4] https://blog.checkpoint.com/wp-content/uploads/2016/07/ HummingBad-Research-report_FINAL-62916.pdf
[5] http://opensignal.com/reports/2015/08/androidfragmentation
[6] https://developer.android.com/about/dashboards/index.html
[7] https://github.com/torvalds/linux/commit/e9c243a5a6de0be 8e584c604d353412584b592f8
[8] https://source.android.com/security/bulletin/2015-09-01. html
[9] https://github.com/torvalds/linux/commit/f0d1bec9d58d4c0 38d0ac958c9af82be6eb18045
[10] http://source.android.com/security/advisory/2016-03-18. html
[11] https://github.com/dynup/kpatch
[12] https://www.ksplice.com/doc/ksplice.pdf
[13] http://events.linuxfoundation.org/sites/events/files/slides/ kGraft.pdf
[14] http://lxr.free-electrons.com/source/include/linux/ livepatch.h
[15] https://conference.hitb.org/hitbsecconf2016ams/sessions/ adaptive-android-kernel-live-patching
[16] https://github.com/lunatik-ng/lunatik-ng
[17] https://play.google.com/store/apps/details?id=eu.chainfire. cfbench&hl=en
[18] https://httpd.apache.org/docs/2.4/programs/ab.html
[19] http://luajit.org
中國(guó)教育網(wǎng)絡(luò)2016年10期