安天移动安全:Janus高危漏洞深度分析
一、背景介紹
近日,Android平臺(tái)被爆出“核彈級(jí)”漏洞Janus(CVE-2017-13156),該漏洞允許攻擊者任意修改Android應(yīng)用中的代碼,而不會(huì)影響其簽名。 眾所周知,Android具有簽名機(jī)制。正常情況下,開發(fā)者發(fā)布了一個(gè)應(yīng)用,該應(yīng)用一定需要開發(fā)者使用他的私鑰對(duì)其進(jìn)行簽名。惡意攻擊者如果嘗試修改了這個(gè)應(yīng)用中的任何一個(gè)文件(包括代碼和資源等),那么他就必須對(duì)APK進(jìn)行重新簽名,否則修改過的應(yīng)用是無法安裝到任何Android設(shè)備上的。但如果惡意攻擊者用另一把私鑰對(duì)APK簽了名,并將這個(gè)修改過的APK對(duì)用戶手機(jī)里的已有應(yīng)用升級(jí)時(shí),就會(huì)出現(xiàn)簽名不一致的情況。因此,在正常情況下,Android的簽名機(jī)制起到了防篡改的作用。
但如果惡意攻擊者利用Janus漏洞,那么惡意攻擊者就可以任意地修改一個(gè)APK中的代碼(包括系統(tǒng)的內(nèi)置應(yīng)用),同時(shí)卻不需要對(duì)APK進(jìn)行重新簽名。換句話說,用這種方式修改過的APK,Android系統(tǒng)會(huì)認(rèn)為它的簽名和官方的簽名是一致的,但在這個(gè)APK運(yùn)行時(shí),執(zhí)行的卻是惡意攻擊者的代碼。惡意攻擊者利用這個(gè)修改過的APK,就可以用來覆蓋安裝原官方應(yīng)用(包括系統(tǒng)的內(nèi)置應(yīng)用)。由此可見,該漏洞危害極大,而且影響的不僅是手機(jī),而是所有使用Android操作系統(tǒng)的設(shè)備。
目前,Google將該漏洞危險(xiǎn)等級(jí)定義為高,其影響Android 5.1.1至8.0的所有版本。基于多年以來針對(duì)移動(dòng)端漏洞的技術(shù)積累和安全對(duì)抗,安天移動(dòng)安全對(duì)Janus高危漏洞進(jìn)行了緊急分析,并發(fā)布技術(shù)報(bào)告,全文如下。
二、漏洞原理
ART虛擬機(jī)在加載并執(zhí)行一個(gè)文件時(shí),會(huì)首先判斷這個(gè)文件的類型。如果這個(gè)文件是一個(gè)Dex文件,則按Dex的格式加載執(zhí)行,如果是一個(gè)APK文件,則先抽取APK中的dex文件,然后再執(zhí)行。而判斷的依據(jù)是通過文件的頭部魔術(shù)字(Magic Code)來判斷。如果文件的頭部魔術(shù)字是“dex”則判定該文件為Dex文件,如果文件頭部的魔術(shù)字是“PK”則判定該文件為Apk文件。
另一方面,Android在安裝一個(gè)APK時(shí)會(huì)對(duì)APK進(jìn)行簽名驗(yàn)證,但卻直接默認(rèn)該APK就是一個(gè)ZIP文件(并不檢查文件頭部的魔術(shù)字),而ZIP格式的文件一般都是從尾部先讀取,因此只要ZIP文件尾部的數(shù)據(jù)結(jié)構(gòu)沒有被破壞,并且在讀取過程中只要沒有碰到非正常的數(shù)據(jù),那么整個(gè)讀取就不會(huì)有任何問題。
總而言之,Android在加載執(zhí)行代碼時(shí),只認(rèn)文件頭,而安裝驗(yàn)證簽名時(shí)只認(rèn)文件尾。
因此只要構(gòu)造一個(gè)APK,從其頭部看是一個(gè)Dex文件,從其尾部看,是一個(gè)APK文件,就可以實(shí)施攻擊。很容易想到,將原APK中的classes.dex抽取出來,改造或替換成攻擊者想要執(zhí)行的dex,并將這個(gè)dex和原APK文件拼起來,合成一個(gè)文件,就可以利用Janus漏洞。
當(dāng)然僅僅簡單地將惡意dex放在頭部,原apk放在尾部合起來的文件還是不能直接用來攻擊。需要稍作修正。對(duì)于頭部dex,需要修改DexHeader中的file_size,將其調(diào)整為合并后文件的大小。另外需要修改尾部Zip,修正[end of central directory record]中[central directory]的偏移和[central directory]中各[local file header]的偏移。
當(dāng)然,Janus漏洞是針對(duì)APK文件的攻擊,因此v1簽名無法抵御這類攻擊,而v2簽名可以抵御。
三、漏洞利用
圖1 攻擊文件拼接原理
具體的漏洞利用分為3步:
- 1.從設(shè)備上取出目標(biāo)應(yīng)用的APK文件,并構(gòu)造用于攻擊的DEX文件;
2.將攻擊DEX文件與原APK文件簡單拼接為一個(gè)新的文件;
3.修復(fù)這個(gè)合并后的新文件的ZIP格式部分和DEX格式部分,修復(fù)原理如圖1所示,需要修復(fù)文件格式中的關(guān)鍵偏移值和數(shù)據(jù)長度值。
最后,將修復(fù)后的文件,重命名為APK文件,覆蓋安裝設(shè)備上的原應(yīng)用即可。
四、漏洞修復(fù)
1.Google官方修復(fù)方案
對(duì)文件system/core/libziparchive/zip_archive.cc打上如下patch
2.修復(fù)原理
打開ZIP格式文件時(shí),多做了一項(xiàng)校驗(yàn),也就是檢測文件的頭部是不是以‘PK’標(biāo)示打頭。如果是,則進(jìn)行正常的邏輯,否則認(rèn)為該文件不是一個(gè)合法的ZIP格式文件。
五、總結(jié)
Android平臺(tái)上的應(yīng)用簽名機(jī)制是Android安全的基石。Android平臺(tái)的permission機(jī)制完全依賴于應(yīng)用的簽名,簽名機(jī)制一旦突破,所有基于Android permission構(gòu)建的安全體系將崩潰。而Janus漏洞已經(jīng)不是Android平臺(tái)的第一例簽名機(jī)制漏洞了,之前由“Bluebox”發(fā)現(xiàn)的Master Key漏洞和“安卓安全小分隊(duì)”(安天移動(dòng)安全上海團(tuán)隊(duì)前身)發(fā)現(xiàn)的第二個(gè)Master Key漏洞都是利用簽名機(jī)制的漏洞,其原理是利用Android的代碼中對(duì)APK驗(yàn)證不充分的缺陷,使得應(yīng)用在安裝時(shí)驗(yàn)證的是原dex,但執(zhí)行的是另一個(gè)dex,從而達(dá)到瞞天過海、偷梁換柱的目的。
Janus漏洞的利用在原理上也類似,它將惡意dex和原apk拼接在一起,安裝驗(yàn)證時(shí)驗(yàn)證的是原apk的dex,而執(zhí)行時(shí)卻是執(zhí)行惡意dex。修復(fù)這類漏洞的原理也很簡單,就是加強(qiáng)安裝時(shí)的驗(yàn)證,避免不合法應(yīng)被安裝到系統(tǒng)中。針對(duì)Janus漏洞,只需簡單驗(yàn)證一下apk文件的頭部是不是‘PK’即可。如果不是,則該apk 文件一定不是一個(gè)正常的apk文件。
Janus漏洞再一次提示我們,即使像Google這樣的跨國科技企業(yè)也難免在簽名驗(yàn)證這么關(guān)鍵的環(huán)節(jié)上多次產(chǎn)生漏洞,特別是Janus漏洞從2014年就已經(jīng)存在,潛伏長達(dá)3年之久,并且從Android 5.1-8.0版本都存在這個(gè)漏洞。這說明了安全問題有時(shí)是極其隱蔽的,暫時(shí)未發(fā)現(xiàn)安全問題,不代表安全問題不存在;更說明了安全是動(dòng)態(tài)的而不是靜止的。因此安全防護(hù)是一個(gè)工程化體系化的持久戰(zhàn),很難通過單次或短期投入就將安全問題一次性解決,在安全方面只有持續(xù)而堅(jiān)定地投入,一旦發(fā)現(xiàn)風(fēng)險(xiǎn)或者漏洞就要以最快的速度及時(shí)修復(fù),只有這樣才能保證系統(tǒng)安全而穩(wěn)定地運(yùn)行,最大程度地規(guī)避風(fēng)險(xiǎn)和損失。
附錄:技術(shù)參考
要理解Janus高危漏洞的原理,首先需要掌握一些基礎(chǔ)知識(shí):ZIP文件結(jié)構(gòu)、DEX文件結(jié)構(gòu)和Android APK簽名機(jī)制。
1. DEX文件結(jié)構(gòu)
圖2 dex文件格式
Dex文件有很多部分組成(如圖2),其中Dex Header最為重要,因?yàn)镈ex的其他組成部分,都需要通過這個(gè)Dex Header中的索引才能找到。 Dex Header內(nèi)部結(jié)構(gòu)如下:
圖3 dex header 結(jié)構(gòu)
在Dex Header中(如圖3),file_size規(guī)定了整個(gè)dex文件的總大小。因此,如果想在Dex文件中隱藏一些額外的數(shù)據(jù)的話,最簡單地,就可以將這些數(shù)據(jù)追加到Dex文件末尾,然后再將file_size調(diào)大到合適的值即可。
2. ZIP文件結(jié)構(gòu)
ZIP文件可以通過獲得文件尾部的End of central directory record(EOCD record)獲取central directory,遍歷central directory中的每項(xiàng)記錄得到的file data即為壓縮文件的數(shù)據(jù)。
表1 ZIP文件結(jié)構(gòu)
如表1,讀取ZIP文件時(shí),會(huì)現(xiàn)從最后一個(gè)記錄區(qū)end of central directory record中讀取central directory的偏移,然后遍歷central directory中的每一項(xiàng),獲取每個(gè)文件的 local file header,最后通過 local file header 獲取每個(gè)文件的內(nèi)容。 End of central directory record結(jié)構(gòu)體如下:
表2 End of central directory record結(jié)構(gòu)
該結(jié)構(gòu)(如表2)中的offset of start of central directory with respect to the starting disk number,指向了central directory的位置。 Central directory結(jié)構(gòu)體如下:
表3 Central directory結(jié)構(gòu)
該結(jié)構(gòu)(如表3)中的relative offset of local header,指向了每個(gè)文件的Local File Header的位置。
因此,如需在ZIP文件中隱藏一些數(shù)據(jù),可將這些數(shù)據(jù)簡單添加到頭部,然后修改End of central directory record中central directory的偏移。同時(shí)修改每個(gè)central directory中的Local File Header的偏移即可。
3.Android APK簽名機(jī)制
Android APK簽名機(jī)制分為兩個(gè)版本:v1和v2版本。
兩個(gè)版本的簽名區(qū)別在于,前者是對(duì)APK中的每個(gè)文件進(jìn)行簽名,如果APK中某個(gè)文件被篡改了,那么簽名驗(yàn)證將會(huì)通不過;后者則是對(duì)整個(gè)APK文件進(jìn)行簽名,只要APK文件的內(nèi)容發(fā)生變化則簽名失效。
很顯然,v2版本要比v1更加嚴(yán)格,安全性會(huì)高很多。 但遺憾的是,Android從7.0開始才引入v2簽名。之前的所有Android系統(tǒng)只能驗(yàn)證v1簽名的app,即使這個(gè)app也用V2簽名了。 以下是兩個(gè)版本的簽名對(duì)比:
表4 v1 v2簽名對(duì)比
對(duì)于android 7.0以上,系統(tǒng)在校驗(yàn)簽名是會(huì)先檢查是否存在V2簽名方案,若存在,則通過V2簽名方案對(duì)APK進(jìn)行校驗(yàn),否則使用V1簽名方案對(duì)APK進(jìn)行校驗(yàn)。
圖4 Android v2簽名流程
對(duì)于android 7.0以下的系統(tǒng),不支持V2簽名方案,所以APK在簽名時(shí)最好將兩種簽名方案都支持。
轉(zhuǎn)載請(qǐng)注明來源:http://blog.avlsec.com/?p=5014
總結(jié)
以上是生活随笔為你收集整理的安天移动安全:Janus高危漏洞深度分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 移动端C#病毒“东山再起”,利用知名应用
- 下一篇: 安天移动安全发布“大脏牛”漏洞分析报告(