同步發表於:http://blog.hacktons.cn/2017/12/25/janus-demo/android
12月9號,Andorid對外曝光了一個名爲Janus
的重量級系統漏洞CVE-2017-13156)
, 由安全研究公司Guard Square發現。
Janus
原意是神話中的二元身,用於描述這個漏洞還真是貼切。git
整個漏洞其實創建在文件校驗規則之上:github
一個文件便是APK,又是DEX,在安裝APK和執行階段的校驗規則差別,致使能夠在APK頭部附加一個惡意DEX來欺騙系統web
下面咱們從市場上隨意下載一個apk來作測試。安全
本文涉及的測試APK,只用於單擊研究之用,請勿惡意散播或上傳,由此引起的糾紛與做者無關
app
能夠從豌豆莢,應用寶等市場下一個測試用的APK,爲了方便,咱們須要選用一些體積較小的apk,若是apk較大頗有可能通過了分包,替換工做會麻煩點。
less
這裏比較噁心的是,下載到的apk並非咱們選取的安裝包,而是豌豆莢市場,既然豌豆莢這麼強勢要入鏡,那麼姑且直接分析豌豆莢市場吧。ide
MD5 (Wandoujia_224660_web_inner_referral_binded.apk) = d3c1d9b2a74a3f8fd9fce38d38423c58
首先檢查下豌豆莢的這個apk是否是v2簽名的,由於咱們要測試的Janus
只能在v1下驗證測試
檢查簽名信息能夠經過*.SF來確認,根據公開信息,若是v2簽名的話,會在SF文件內寫入一個字段X-Android-APK-Signed:2
;
豌豆莢
的SF文件名字是META-INF/DEAMON2.SF
, 比較幸運啊,能夠確認其使用的就是v1簽名。google
aven$ unzip -l Wandoujia_224660_web_inner_referral_binded.apk |grep META-INF 120009 12-15-17 14:38 META-INF/MANIFEST.MF 120130 12-15-17 14:38 META-INF/DEAMON2.SF 891 12-15-17 14:38 META-INF/DEAMON2.RSA
aven$ unzip -p Wandoujia_224660_web_inner_referral_binded.apk META-INF/DEAMON2.SF|less Signature-Version: 1.0 SHA1-Digest-Manifest-Main-Attributes: jq/6qzaCk3O+H4OBJsDhMXm+FvE= Created-By: 1.6.0_30 (Sun Microsystems Inc.) SHA1-Digest-Manifest: Dts4zfEM9pZstNDahVfVh4e4jGA= Name: res/drawable-xhdpi-v4/il.png SHA1-Digest: QCves3Cr/wm3X2w4PR4ESXGMBOw= Name: res/layout/dh.xml SHA1-Digest: DCuKb0PRLuNV6jTEbSDGMTEW174=
接下來咱們須要構造一個新的dex,嫁接到豌豆莢的apk前面;這裏須要確認豌豆莢使用的包名:com.wandoujia.phoenix2
package: name='com.wandoujia.phoenix2' versionCode='16861' versionName='5.68.21' sdkVersion:'14' targetSdkVersion:'16'
另外值得一提的是,豌豆莢的權限仍是比較流氓
的會要求大量敏感權限,所以在使用該市場的時候注意權限的問題,不然頗有可能裸奔了:
好比讀/寫短信,讀/寫通信錄等等,還有一些第三方權限
uses-permission:'android.permission.READ_SMS' uses-permission:'android.permission.RECEIVE_SMS' uses-permission:'android.permission.MANAGE_ACCOUNTS' uses-permission:'android.permission.AUTHENTICATE_ACCOUNTS' uses-permission:'android.permission.USE_CREDENTIALS' uses-permission:'android.permission.READ_SETTINGS' uses-permission:'android.permission.READ_EXTERNAL_STORAGE' uses-permission:'android.permission.SEND_SMS' uses-permission:'android.permission.WRITE_EXTERNAL_STORAGE' uses-permission:'android.permission.MOUNT_UNMOUNT_FILESYSTEMS' uses-permission:'android.permission.INTERNET' uses-permission:'android.permission.ACCESS_NETWORK_STATE' uses-permission:'android.permission.ACCESS_WIFI_STATE' uses-permission:'android.permission.CHANGE_WIFI_STATE' uses-permission:'android.permission.CHANGE_WIFI_MULTICAST_STATE' uses-permission:'android.permission.SET_WALLPAPER' uses-permission:'android.permission.SET_WALLPAPER_HINTS' uses-permission:'android.permission.WRITE_SETTINGS' uses-permission:'android.permission.CAMERA' uses-permission:'android.permission.FLASHLIGHT' uses-permission:'com.android.launcher.permission.INSTALL_SHORTCUT' uses-permission:'com.android.launcher.permission.UNINSTALL_SHORTCUT' uses-permission:'android.permission.READ_PHONE_STATE' uses-permission:'android.permission.MODIFY_AUDIO_SETTINGS' uses-permission:'android.permission.SYSTEM_ALERT_WINDOW' uses-permission:'android.permission.ACCESS_SUPPERUSER' uses-permission:'android.permission.GET_PACKAGE_SIZE' uses-permission:'android.permission.KILL_BACKGROUND_PROCESSES' uses-permission:'android.permission.CLEAR_APP_CACHE' uses-permission:'android.permission.DISABLE_KEYGUARD' uses-permission:'com.android.launcher.permission.READ_SETTINGS' uses-permission:'com.android.launcher.permission.WRITE_SETTINGS' uses-permission:'com.android.launcher3.permission.READ_SETTINGS' uses-permission:'com.android.launcher3.permission.WRITE_SETTINGS' uses-permission:'com.meizu.flyme.launcher.permission.READ_SETTINGS' uses-permission:'com.meizu.flyme.launcher.permission.WRITE_SETTINGS' uses-permission:'org.adw.launcher.permission.READ_SETTINGS' uses-permission:'org.adw.launcher.permission.WRITE_SETTINGS' uses-permission:'com.qihoo360.launcher.permission.READ_SETTINGS' uses-permission:'com.qihoo360.launcher.permission.WRITE_SETTINGS' uses-permission:'com.lge.launcher.permission.READ_SETTINGS' uses-permission:'com.lge.launcher.permission.WRITE_SETTINGS' uses-permission:'net.qihoo.launcher.permission.READ_SETTINGS' uses-permission:'net.qihoo.launcher.permission.WRITE_SETTINGS' uses-permission:'org.adwfreak.launcher.permission.READ_SETTINGS' uses-permission:'org.adwfreak.launcher.permission.WRITE_SETTINGS' uses-permission:'com.huawei.launcher3.permission.READ_SETTINGS' uses-permission:'com.huawei.launcher3.permission.WRITE_SETTINGS' uses-permission:'com.fede.launcher.permission.READ_SETTINGS' uses-permission:'com.fede.launcher.permission.WRITE_SETTINGS' uses-permission:'com.sec.android.app.twlauncher.settings.READ_SETTINGS' uses-permission:'com.sec.android.app.twlauncher.settings.WRITE_SETTINGS' uses-permission:'com.anddoes.launcher.permission.READ_SETTINGS' uses-permission:'com.anddoes.launcher.permission.WRITE_SETTINGS' uses-permission:'com.lenovo.launcher.permission.READ_SETTINGS' uses-permission:'com.lenovo.launcher.permission.WRITE_SETTINGS' uses-permission:'com.google.android.launcher.permission.READ_SETTINGS' uses-permission:'com.google.android.launcher.permission.WRITE_SETTINGS' uses-permission:'com.oppo.launcher.permission.WRITE_SETTINGS' uses-permission:'com.oppo.launcher.permission.READ_SETTINGS' uses-permission:'com.yulong.android.launcher3.permission.WRITE_SETTINGS' uses-permission:'com.yulong.android.launcher3.permission.READ_SETTINGS' uses-permission:'com.huawei.android.launcher.permission.READ_SETTINGS' uses-permission:'com.huawei.android.launcher.permission.WRITE_SETTINGS' uses-permission:'com.htc.launcher.permission.READ_SETTINGS' uses-permission:'com.htc.launcher.permission.WRITE_SETTINGS' uses-permission:'com.bbk.launcher2.permission.READ_SETTINGS' uses-permission:'com.bbk.launcher2.permission.WRITE_SETTINGS' uses-permission:'android.permission.WAKE_LOCK' uses-permission:'android.permission.BROADCAST_PACKAGE_ADDED' uses-permission:'android.permission.BROADCAST_PACKAGE_CHANGED' uses-permission:'android.permission.BROADCAST_PACKAGE_INSTALL' uses-permission:'android.permission.BROADCAST_PACKAGE_REPLACED' uses-permission:'android.permission.RESTART_PACKAGES' uses-permission:'android.permission.GET_TASKS' uses-permission:'android.permission.RECEIVE_BOOT_COMPLETED' uses-permission:'android.permission.CHANGE_NETWORK_STATE' uses-permission:'android.permission.GET_ACCOUNTS' uses-permission:'android.permission.VIBRATE' uses-permission:'android.permission.BIND_ACCESSIBILITY_SERVICE' uses-permission:'android.permission.READ_CONTACTS' uses-permission:'android.permission.WRITE_CONTACTS' uses-permission:'android.permission.CALL_PHONE' uses-permission:'android.permission.WRITE_SMS' uses-permission:'android.permission.WRITE_CALL_LOG' uses-permission:'android.permission.READ_CALL_LOG' uses-permission:'android.permission.AUTHENTICATE_ACCOUNTS' uses-permission:'android.permission.WRITE_SYNC_SETTINGS' uses-permission:'android.permission.MANAGE_ACCOUNTS' uses-permission:'android.permission.ACCESS_FINE_LOCATION' uses-permission:'android.permission.ACCESS_COARSE_LOCATION' uses-permission:'com.wandoujia.phoenix2.permission.MIPUSH_RECEIVE' uses-permission:'android.permission.PACKAGE_USAGE_STATS' uses-permission:'android.permission.PERSISTENT_ACTIVITY' uses-permission:'android.permission.ACCESS_MTK_MMHW'
接下來開始編碼工做,明確下咱們的目標:
所以首先安確認下豌豆莢的自定義application:com.pp.assistant.PPApplication
。
aven$ aapt dump xmltree Wandoujia_224660_web_inner_referral_binded.apk AndroidManifest.xml|less E: application (line=155) A: android:theme(0x01010000)=@0x7f0a0001 A: android:label(0x01010001)=@0x7f0c038a A: android:icon(0x01010002)=@0x7f02009d A: android:name(0x01010003)="com.pp.assistant.PPApplication" (Raw: "com.pp.assistant.PPApplication") A: android:stateNotNeeded(0x01010016)=(type 0x12)0xffffffff A: android:windowSoftInputMode(0x0101022b)=(type 0x11)0x3 A: android:allowBackup(0x01010280)=(type 0x12)0xffffffff
建立同名的PPApplication的,而後加上toast便可,接下來編譯獲得新的apk,並將其中的dex抽離出來備用。
在實際插入dex的時候,遇到了一些小插曲,好比插入完後,啓動崩潰,因此若是是插入全新的dex的話,須要確認和原有dex的關係,若是徹底摒棄原有邏輯,那麼須要手動補全manifest中聲明的ContentProvider
和BroadcastReceiver
,Activity根據須要替換,Service可選替換
另外合併apk和dex不是簡單的字節疊加,須要修改最終apk的偏移量,確保zip的正確性。筆者使用的是一個Python腳本
https://github.com/V-E-O/PoC/tree/master/CVE-2017-13156
搞定以後,能夠直接安裝apk,也能夠覆蓋升級安裝,接下來啓動app就能夠看到徹底不一樣的效果;
在這裏咱們出於實驗性質,將豌豆莢市場的application和啓動Activity作了總體替換,所以直接感覺就是原有邏輯所有沒有了,若是咱們經過反編譯後增量修改的方式來新增dex,納悶能夠實現和原app功能幾乎一致的串改,這樣能夠惡意插入代碼,同時不容易被用戶發現。
這個bug看起來挺嚴重的,不過實際上影響有限,若是用戶經過正規市場下載程序基本沒什麼問題,同時Android官方已經作fix,相信後續很快就會在新版本中生效。 對於開發者來講比較被動,最好升級簽名爲V2,別的就沒有屏蔽辦法了,比較問題出在系統校驗上面。