前言:
360手機安全研究團隊vulpecker近日發(fā)現(xiàn)了一種新型的安卓app安全漏洞,市面上數(shù)以千萬的app都受該漏洞影響。該漏洞一旦被攻擊者利用,可以直接在用戶手機中植入木馬,盜取用戶的短信、照片以及銀行、支付寶等賬號密碼,vulpecker以“寄生獸”命名這個漏洞。
目前vulpecker團隊已經(jīng)通過補天平臺將相關詳情通知給各大安全應急響應中心,也向受此影響的各大廠商進行了通報,在此提醒用戶關注各APP廠商修復進程,并及時下載更新安裝最新的APP。
寄生獸是日本作家?guī)r明均創(chuàng)作的漫畫《寄生獸》中的一種怪物,初始形態(tài)是一種蟲子,會鉆進生物的體內并奪取大腦,因人類嚴重的環(huán)境污染而誕生,該漏洞的攻擊方式類似寄生獸的感染,可以長期駐留在受害者的手機內,本文將詳細分析這個漏洞,揭開漏洞的秘密。
一.關于app的緩存代碼
安卓的應用程序apk文件是zip壓縮格式的文件,apk文件中包含的classes.dex文件相當于app的可執(zhí)行文件,當app運行后系統(tǒng)會對classes.dex進行優(yōu)化,生成對應的odex格式的文件。
odex文件相當于app的可執(zhí)行文件的緩存代碼,一般安卓系統(tǒng)在第一次加載運行apk時會將系統(tǒng)生成odex文件存放于/data/dalvik-cache目錄下。
如圖:
可以看到該目錄下的文件只有system用戶有寫權限,只有在擁有system權限的情況下才能對odex文件進行寫操作。
二.廣泛流行的插件機制
由于安卓應用的升級都需要重新安裝程序,頻繁的升級給用戶體驗和開發(fā)都帶來了不便,所以市面上的app都開始采用插件機制,利用插件機制可以做到無縫升級和擴展功能,app只需要引入相應的插件文件就可以做到功能添加或升級,無需再重新安裝程序。
app插件機制的實現(xiàn)方式是把相關功能編寫成單獨的apk或jar文件,然后在程序運行時用DexClassLoader動態(tài)加載,進行反射調用。我們來看一下DexClassLoder的定義
public DexClassLoader (String dexPath, String optimizedDirectory, String library
Path, ClassLoader parent)
dexPath:是要加載的jar/apk的路徑
optimizedDirectory:目標odex的路徑
libraryPath:依賴的native library(so文件)路徑
parent:父加載器
下面是常見的調用DexClassLoader的代碼片段
String dexFiles = “/data/data/com.test.dexload/app_al_sdk/drozer.apk”;
2. final File optimizedDexOutputPath = appcontext.getDir(“outdex”, 0);
3. appcontext.getClassLoader();
4. DexClassLoader classLoader = new DexClassLoader(dexFiles, optimizedDexOutputPath
.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
5. …
如圖drozer.apk插件在被調用后生成了drozer.dex緩存文件,注意dex這個文件是odex格式,且這個目錄是app的私有目錄。
三. 插件機制引入的攻擊點
在2013年,國外的mwr實驗室給出了一個利用中間人的方式劫持app升級插件的攻擊案例,參考
https://labs.mwrinfosecurity.com/blog/2013/11/20/applovin-ad-library-sdk-remote-command-execution-via-update-mechanism/幾年前,大部分采用插件機制的app,在載入插件前都沒有對插件文件進行完整性校驗,導致黑客可以通過中間人劫持的方式替換app的升級插件,在插件中嵌入惡意代碼控制用戶的app和手機。
現(xiàn)今,大部分采用插件機制的app都加強了安全性,如最早使用插件開發(fā)方式的微信等app,在下載使用插件前都會校驗插件文件的簽名,黑客已經(jīng)無法通過中間人的方式替換插件攻擊app。
四. 插件機制新的攻擊點
近日,國外的nowsecure公司公布了三星輸入法的一個漏洞,利用過程直接替換了系統(tǒng)app的odex緩存代碼。參考:
https://www.nowsecure.com/blog/2015/06/16/remote-code-execution-as-system-user-on-samsung-phones/三星輸入法是擁有系統(tǒng)最高級別的 system 權限,可以直接替換任意app的緩存文件。那安卓app插件的緩存代碼是否和APP主程序直接產(chǎn)生的緩存代碼一樣能被任意替換?
我們去android源碼中驗證了一下,通過DexClassLoader() 加載jar/apk文件,最終會通過native接口openDexFileNative() 進入到native層。
對應于android-4.2.2_r1/dalvik/vm/native/dalvik_system_DexFile.cpp中的Dalvik_dalvik_system_DexFile_openDexFileNative() 方法,在native層對幾個參數(shù)做一系列校驗,如果檢測到第二個參數(shù)指定的odex文件存在,則會調用dvmOpenCachedDexFile() 直接打開,調用處的代碼如下:
fd = dvmOpenCachedDexFile(fileName, cachedName,
dexGetZipEntryModTime(&archive, entry),
dexGetZipEntryCrc32(&archive, entry),
isBootstrap, &newFile, /*createIfMissing=*/true);
很明顯,第3、4個參數(shù)對應的是優(yōu)化前的classes.dex的時間戳和crc校驗值。最終會調用
dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc,
expectVerify, expectOpt)
如果crc、modWhen參數(shù)正確,則返回該odex的文件句柄;若crc、modEWhen校驗錯誤,則嘗試刪除錯誤的odex,并重建新的odex。所以,攻擊者如果要注入目標odex,需要對修改后的odex文件的crc及modWhen做修改。
下面是一個修改后的odex文件實例,dex_old是修改前的odex文件,dex_new是修改后的dex文件,兩個文件的md5不一樣,但是crc及modWhen卻是一樣的,這樣就可以繞過DexClassLoader的校驗。
五. “寄生獸”漏洞的真正危害
安卓應用的代碼緩存機制是程序在執(zhí)行時優(yōu)先加載運行緩存代碼,而google卻只對緩存代碼做了可以偽造的弱校驗,這明顯是一個安全架構實現(xiàn)上的嚴重漏洞。
廣大app開發(fā)者在使用插件機制開發(fā)app時可以對插件文件做完整性校驗,而系統(tǒng)生成的緩存代碼卻無法做到有效保護,一旦攻擊者將惡意代碼注入到緩存代碼中,開發(fā)者對app插件文件做的各種保護都將失效。這種攻擊很難被發(fā)現(xiàn),即使關機后重啟,只要app一運行,惡意代碼也會隨之運行,同時安全軟件對這一塊的檢查和防御也幾乎為零。
六.現(xiàn)實中的“寄生獸”漏洞攻擊案例
(1)利用zip解壓縮漏洞覆蓋緩存代碼
在三星輸入法漏洞的利用中,作者用到了安卓下的zip解壓縮漏洞,這個漏洞是單獨的一個漏洞,且由來以久,在google官方的文檔中已經(jīng)做了警告,存在問題的是ZipEntry.getName()方法,我們看一下google文檔中對該函數(shù)的描述:
鏈接:http://developer.android.com/reference/java/util/zip/ZipEntry.html#getName()
Gets the name of this ZipEntry
Security note: Entry names can represent relative paths. foo/../bar or ../bar/baz ,
for example. If the entry name is being used to construct a filename or as a path
component, it must be validated or sanitized to ensure that files are not written outside
of the intended destination directory.
可以看到google對該方法給出了一個安全提示,提示開發(fā)者如果該方法的返回值中包含有”../”跳轉符,需要特別注意不要將文件寫到了目標文件夾之外。如果不對”../”跳轉符做過濾,就有可能遍歷目錄,在解壓zip文件時以本app的權限覆蓋任意文件。
下面是一個安卓zip解壓縮的常用代碼片段
1. ZipFile zip = new ZipFile(zipFile);
2. for(Enumeration entries = zip.entries();entries.hasMoreElements();){
3. ZipEntry zipEntry = (ZipEntry)entries.nextElement();
4. File file = new File(outputDirectory + File.separator+ zipEntry.getName());
5. …
6. }
如果沒有對 zipEntry.getName進行檢查,盲目解壓創(chuàng)建文件,將會穿越目錄建立文件,如圖:
我們檢測后發(fā)現(xiàn)市面上幾乎所有使用zip解壓縮功能的app都存在漏洞,為“寄生獸”漏洞的攻擊提供了便利,主要分為三類情況:
APP關聯(lián)文件類
這類漏洞主要影響有皮膚功能的APP,如輸入法,瀏覽器類APP .很多app在manifest中做了zip類文件的關聯(lián),如果注冊的文件格式被點擊,對應的app就會啟動解壓文件。下圖是app注冊文件關聯(lián)的一個示例
這個app關聯(lián)了一個ssf格式的文件,其實這個文件的格式是zip壓縮格式,用戶在手機中下載打開ssf文件時,就會啟動對應的app自動解壓文件,文件中包含的惡意代碼可以覆蓋該app的緩存代碼。
驗證某輸入法app漏洞視頻
APP自升級類
這類漏洞主要影響有自動升級下載zip類文件功能的app,在app下載文件過程中可以被中間人劫持攻擊,我們發(fā)現(xiàn)地圖類的app和sdk插件最容易收到攻擊,app在下載解壓資源文件的過程中被攻擊
驗證某地圖app漏洞視頻
APP默認解壓類
這類漏洞主要影響默認有解壓縮zip文件功能的app,如瀏覽器直接下載zip文件打開后,app就被感染緩存代碼。
驗證某瀏覽器漏洞視頻:
(2)利用adb backup覆蓋緩存代碼
如果開發(fā)者沒有在manifest里指定allowBackup="false" ,就可以在不需要root權限的情況下備份、恢復app私有目錄下的數(shù)據(jù)。如果該app用到了插件機制,則對應的插件的odex文件也會被備份。攻擊者可以先用adb backup備份用戶數(shù)據(jù),對備份下來的odex文件進行修改,然后用adb restore恢復回去,就可以替換掉正常的odex文件,造成代碼劫持。
(3)其他可能的APP數(shù)據(jù)讀寫
如果一個木馬病毒利用root權限實施“寄生獸”漏洞攻擊方式,將能實現(xiàn)隱蔽的apt木馬攻擊方式,長期潛伏在用戶的手機類,安全軟件很難發(fā)現(xiàn)app的緩存代碼被感染了。
七. “寄生獸”漏洞的防護方案
“寄生獸”漏洞的核心有兩點,一是google沒有考慮odex的安全問題需要開發(fā)者自己做防護,另一個是要阻斷漏洞的攻擊入口和利用方式,這里我們給出一些防護建議緩解該漏洞的攻擊。
(1)對odex文件進行完整性校驗
由于對odex一般是由系統(tǒng)(DexClassLoader)自動生成的,且odex與apk/jar是相對獨立的,開發(fā)者事先無法知道odex文件的MD5等信息,所以很難通過MD5校驗等手段保護odex的完整性;同時,系統(tǒng)的DexClassLoader函數(shù)只是校驗了odex中的crc、modWhen字段,可以很輕易的被繞過。
所以,目前對odex的防護只能由app自身來做,可以在每次運行DexClassLoader之前,清除已經(jīng)存在的odex;
另外,在odex第一次生成之后,存儲odex文件的MD5值,以后每次調用DexClassLoader的時候都對odex文件進行MD5校驗。
(2)對可能的劫持odex的攻擊入口漏洞進行修復
對zip解壓縮的漏洞,只需要在調用zipEntry.getName()的時候,過濾返回值中的”../”跳轉符。
對于引用的第三方的zip庫也需要注意,可以用上面的測試用例測試一下第三方庫是否有zip解壓縮的漏洞;
調用DexClassLoader動態(tài)加載dex的時候,第二個參數(shù)不要指定在sdcard上;
在manifest里指定allowBackup=”false”,防止應用數(shù)據(jù)備份覆蓋
【原文:
影響數(shù)千萬APP的安卓APP“寄生獸”漏洞技術分析 安全脈搏 Expl0r3r 整理發(fā)布】