最近由印第安纳大学以及微软的研究人员(下文简称:研究人员)共同发现了Android系统上一直存在的一个漏洞,并发表了相应的论文,论文中称此漏洞为“Pileup”。此漏洞涉及范围广泛,几乎涉及到了目前所有的Android发行版本。
那么到底是怎样的一个漏洞会有如此大的影响范围呢?下面让我们一探究竟。
Pileup 漏洞是研究人员对于“privilegeescalation through updating”简称,此漏洞存在于Android的系统更新过程。研究人员发现在Android系统的OTA更新流程中存在着一些可以被恶意软件所利用的漏洞,通过这些漏洞,恶意软件可以静默获取一些系统应用的permission,阻止系统应用的安装,修改某些系统应用的数据,阻止Google Play services的安装等。
在了解Pileup漏洞之前,首先要了解一下Android系统OTA更新的流程。到目前为止Google官方还没有正式发布过OTA更新流程的标准文档,下面的更新流程是根据第三方报告,研究人员对于代码的分析以及实际操作中的系统log总结出来的:
1、用户在手机的设置里手动检查是否有可用更新(或者系统自己定时检查是否有可用的更新),如果有可用更新,则提示用户升级;
2、 用户选择升级,系统通过网络从更新包所在的服务器下载对应的更新包;
3、 更新包下载完成后,系统重新启动进入Recovery模式,进行升级操作。在进入Recovery模式后,首先会对更新包做合法性和完整性的检查,然后用更新包里的文件替换之前系统中旧的文件,最后将更新结果写入一个文件中(此文件的名字和保存路径根据手机厂商的不同而不同),重新启动手机进入新的系统;
4、手机重新启动后,系统会通过不同的系统组件来完成剩下的更新操作,其中Package Manager Service(PMS)会将所有的系统应用和第三方应用重新安装一遍;
5、以上所有操作完成后,OTA更新结束;
Android OTA 系统更新是会保留旧的系统中用户自己安装的应用及其数据、系统设置、短信、通讯录等信息和数据,而基于此目的而制定的以上OTA系统更新流程中存在着以下几个可以被利用的漏洞。
1、permission相关漏洞:
由于PMS在处理系统更新后的permission相关逻辑上的问题,恶意应用可以在不经过用户允许的情况下直接获取到dangerous甚至是system和signature级别的permission。而system和signature级别的permission都是给系统应用使用的。那么恶意应用是如何获取这些permission的呢?
所有应用在被安装的时候,PMS都会去检查应用申请的所有permission,但是在此过程中,PMS会忽略那些无法识别的permission,并且也不会把这些无法识别的permission告知用户。如果一个恶意应用申请了一些在旧的系统中没有但是在升级后的高版本的系统中新增的permission,在旧的系统中安装的此应用的时候PMS不会将这些在旧系统中无法识别的permission告知用户。而在系统更新完成后,这些permission虽然已经是可以识别的了,但是由于恶意应用是在旧系统中已经安装的应用,所有permission也通过了用户允许,所以在新的系统里PMS也不会将这些permission再告知用户,这样恶意应用就在用户不知情的情况下,静默的获取到了这些在旧的系统里不存在,而在新的系统里存在的permission。需要注意的是,通过这种方式只能获取 dangerous级别的permission。
那么是否可以通过类似的方法获取到system和signature级别的permission呢?是有方法的。恶意应用可以在旧的系统中自己定义那些在新的系统中新增的permission,这样在旧的系统中安装恶意应用的时候,PMS会把恶意应用定义的permission添加到PMS的permission列表里,然后用这个permission来保护相应的代码。当系统更新到新的系统之后,PMS会首先读取所有已经在旧系统中存在的permission,并把保存到mSettings.mPermissions 这个list里面。当PMS再去注册那些新的系统中的系统应用定义的新增的permission的时候,会先检查mSettings.mPermissions这个list,如果新增的permission已经存在并且所注册的包名不一致的话就回跳过对新的系统应用中新增permission的注册。这样就会使得恶意应用窃取了本该由系统应用所应该拥有的权限。
图1 Android各个版本新增的一些permission[1]
2、Shared UID相关漏洞:
此漏洞可以被恶意应用利用来阻止新的系统中的某些系统应用的安装。当一个恶意应用在低版本的系统中声明了一个在高版本系统中的系统应用才使用的Shared UID,那么在系统从低版本更新到高版本的过程中,PMS就会跳过新系统中的系统应用的安装。
那么此漏洞是怎么被利用的呢?当系统更新后,PMS会按照先系统应用后第三方应用的顺序来依次安装新增的应用以及重新安装在旧的系统中已经安装过的所有应用。而在此过程中,如果一个第三方应用使用了跟系统应用一样的包名的话,这个第三方应用会因为包名冲突而无法安装,因为系统应用是会比第三方应用先安装的。但是当这个第三方应用也使用了Shared UID的时候,PMS就会区别对待。当安装一个系统应用的时候,PMS会创建一个pkgSetting实例,用来保存这个应用的所有设置信息。而这个pkgSetting里的所有信息通常都来自于应用自身。但是当PMS在查找mSettings这个list的时候,如果发现了包名冲突(在旧的系统中就已经存在包名完全相同的应用),此时PMS就会查看这两个应用的Shared UID,如果这两个应用使用了相同的Shared UID(包括Shared UID是空的情况),那么pkgSetting的所有信息就会从旧系统中已经存在的那个应用加载。而在这个过程中,当两个应用的Shared UID相同且非空的时候,PMS会去检查两个应用是否使用了同样的签名,如果签名不一致,那么新增的系统应用就不会被安装,而旧系统中已经存在的那个应用会在稍后被安装。
图2 研究人员发现的可以被利用的UID[1]
3、应用的数据相关漏洞:
Android系统的所有应用无论是/system/app/还是/data/app/下的应用的数据都是保存在/data/data/目录下以应用的包名为目录名的路径下。如果在低版本的系统中安装了一个与高版本新增的系统应用同样包名的恶意应用,那么在更新后,如果这两个应用都没有使用Shared UID的话,由于包名冲突,PMS会安装高版本系统中新增的应用,低版本中的安装的第三方应用将不再被安装。但是由于两个应用的包名是一样的,所以新安装的系统应用仍然会使用低版本中恶意应用的数据目录。恶意应用就可以利用这个漏洞在数据目录下留下一些恶意数据给新的系统应用使用。在Android2.3版本中默认浏览器的包名是:com.android.browser,但是在Android4.0版本中默认浏览器的包名改为了:com.google.android.browser。根据此漏洞原理,如果在2.3版本中安装了一个包名为:com.google.android.browser的恶意应用,并且在缓存,数据库中加入一些恶意链接和脚本。当用户使用更新后的系统中的浏览器的时候,就是使用这些被恶意篡改的数据,给用户带来危害。
图3 研究人员发现的可被利用的包名[1]
4、permission-tree相关的漏洞:
在Android系统中,一个应用是可以在manifest文件中定义一个permissiontree[2]的。这里的permission tree就是一组用于相同命名空间的根命名。如果定义了一个叫com.example的permission tree的话,那么基于com.example的如:com.example.math1,com.example.math2,com.example.math2.add等都是属于这个permissiontree的。而一个应用一旦定义了一个permission tree的话,那么这个应用就会拥护所有这个permission tree命名空间下的permission的控制权。可以在运行时动态的添加属于这个permission tree命名空间下的任何一个permission。同时在Android系统中是不允许存在两个同样名字的permission的。而通过在低版本的系统中定义一个可以覆盖到高版本的系统应用新增的permission的permission tree的方式,就可以使得恶意应用获取到新的系统应用的permission。那么具体是怎么做到的呢?
在系统更新过程中,PMS在注册任何新的permission之前,都会检查mSettings下的mPermissiontrees这个list,当发现这个list里的任何一个permissiontree的命名空间可以覆盖到这个要新注册的permission并且这个permission tree的注册者和新的要注册的应用的包名不一致时,注册新的permission的流程就会失败,系统应用也就无法注册新增的这个permission。而且研究人员发现,在Google Nexus中,虽然系统应用google.android.gsf声明了一个为:google.apps.permission.GOOGLE_AUTH的permission tree,但是恶意应用仍然可以成功声明一个为:google.apps.permission的permission tree。这里显然恶意应用所声明的permission tree的命名空间更广。这样导致的结果就是即使在新的系统中新增的permission是属于google.apps.permission.GOOGLE_AUTH这个命名空间的也无法注册成功,因为这些permission已经被恶意应用所声明的permissiontree的命名空间所覆盖到。
5、阻止安装Google PlayServices 漏洞:
GooglePlay Services 是Google从Android 4.0版本开始添加的用于提供更新google play下载的应用、同步帐户以及访问私人设置等功能的一个包。研究人员发现,当系统从2.3版本升级到4.0版本的时候,Google Play Services的包并没有包含在更新包中,而是升级到4.0版本以后,再单独从网络上下载并安装的。所以利用PMS不允许安装两个包名相同的应用的规则,在2.3版本的系统上安装上一个与Google play services相同包名的恶意应用的话,在系统升级到4.0版本以后就无法安装真正的Google Play Services。这样就会导致所有依赖Google Play Services的应用无法正常运行。
参考资料:
[1] Luyi Xing, Xiaorui Pan, Rui Wang, KanYuan and XiaoFeng Wang:Upgrading Your Android, ElevatingMy Malware:Privilege Escalation Through Mobile OS Updating
[2] Permission Treee
http://developer.android.com/guide/topics/manifest/permission-tree-element.html.