导语:近日,在Android系统中发现了一个严重的漏洞(c2017-13156),其允许攻击者在不影响签名的情况下修改应用程序中的代码。该漏洞的原因在于,一个文件可以同时是有效的APK文件和有效的DEX文件。
近日,在Android系统中发现了一个严重的漏洞(c2017-13156),其允许攻击者在不影响签名的情况下修改应用程序中的代码。该漏洞的原因在于,一个文件可以同时是有效的APK文件和有效的DEX文件。该漏洞以罗马的双面神命名,我们称之为Janus漏洞。
Janus漏洞
Janus漏洞利用的是给APK文件和DEX文件添加额外字节的可能性。一方面,APK文件是一个zip归档文件,在其zip条目之前(实际上普遍是在zip条目之间),该文件开头可以包含任意字节。JAR签名方案只考虑zip条目。它忽略了当计算或验证应用程序的签名时的任何其他字节。另一方面,DEX文件在结束时,在字符串、类、方法定义等常规部分之后可以包含任意字节。因此,可以同时既是一个有效的APK文件,又是一个有效的DEX文件。
另一个关键元素是Dalvik/ART虚拟机的一个看似无害的特性。从理论上讲,Android运行时加载APK文件,提取它的DEX文件,然后运行它的代码。但是在实践中,虚拟机可以加载和执行APK文件和DEX文件。当虚拟机加载的是一个APK文件时,它仍然会查看文件头中的魔法字节来决定它是哪种类型的文件。如果它识别到了DEX文件头,就会将文件加载为一个DEX文件。否则,它将文件加载为包含DEX文件zip条目的APK文件。因此,虚拟机可能会错误地解释双重DEX/APK文件。
攻击者可以利用虚拟机的这种特性,在不影响其签名的情况下,将一个恶意的DEX文件加在APK文件前面。Android运行时接受APK文件作为该应用合法的早期版本的有效更新。然而,Dalvik VM加载来自被注入的DEX文件中的代码。
尽管Android应用程序是自签名的,但在更新Android应用程序时,签名验证非常重要。当用户更新应用程序时,Android运行时会将其签名与原始版本的签名进行比较。如果签名匹配,Android运行时将继续安装更新。更新后的应用程序继承原始应用程序的权限。因此,攻击者可以使用Janus漏洞来误导更新进程,并在不知情的用户设备上安装具有较大权限的未经验证的代码。
我们可以想象可能会出现的一些比较严重的情况。攻击者可以通过修改后的更新来替换具有较高权限受信任的应用程序(如,一个系统应用程序),从而滥用它的权限。在替换掉目标应用程序的基础上,黑客可能能够访问存储在设备上的敏感信息,甚至可以完全接管设备。或者,攻击者可以将敏感应用程序修改后的克隆版本作为合法的更新,例如在涉及银行或通信应用的应用程序。克隆的应用程序的外观和功能跟最初的应用程序一样,但是会被注入恶意的行为。
zip文件格式陈旧,容易出现像Master Key漏洞和本文提到的Janus漏洞这样的问题。模糊的zip文件可能会在不同的环境和不同的系统中导致相似的漏洞。其根本原因是格式的冗余。因此一般在设计数据格式、协议、数据结构和代码时,应该始终尽力避免冗余。任何差错都可能导致出现bug或更糟的情况。
影响范围和防范措施
我们已经创建了一个简单的内部工具将创建Janus应用程序作为概念的证明。此时,我们还没有大范围的发现这样的应用。
任何坚持要求用户从Google Play商店外的一个源安装恶意更新的情况,欺骗一些用户可能相对比较容易,因为应用程序看起来仍然与原始应用程序完全相同,并且具有正确的签名。但是对于专家来说,如果通用的反向工程工具并不显示注入的代码,在下载应用程序和更新时,用户就应该始终保持警惕了。
Janus漏洞影响了最近的Android设备(Android 5.0和更新版本)。已经与APK签名方案v2签署的应用程序以及支持最新签名方案的设备上运行的应用程序(Android 7.0和更新版本)都受到了保护。与方案 v1不同,方案v2考虑了APK文件中所有的字节。旧版本的应用程序和运行在旧设备上的新应用程序仍然很容易受到影响。开发者至少应该只用签名方案v2。
使用DexGuard的篡改检测机制的Android应用程序可以更好地抵御克隆攻击。该机制执行额外的检查以确保受保护的应用程序没有以任何方式被修改。我们建议使用篡改检测和DexGuard的其他保护层来防止逆向工程和克隆。
信息披露和解决办法
我们在2017年7月31日向谷歌报告了这个问题,并在同一天收到了确认。谷歌在11月向其合作伙伴发布了补丁。他们在2017年12月4日的Android安全公报上发布了这一漏洞(c2017-13156)。