探究一种Android安全解决方案
一 引言
Android系统由Google公司联合开放手机联盟OHA于2007年11月发布,正是由于Android强大的功能和开源的特性,Android一经推出就受到市场的热销,但随之而来的是Android的安全问题,许多恶意软件的作者瞄准了Android系统,恶意扣费,远程控制,隐私泄露等等安全问题接踵而来。国内外已经有许许多多专家和学者围绕着Android安全开展来了一系列深入的研究,其中关注Android权限的研究确比较少。Android强烈依赖于权限检查机制,玩过Android手机的朋友都知道,每当用户安装一款新的软件,在安装界面上Android总会提示用户此软件所需要的权限,用户要么全部接受这些权限要求,要么否定本次安装过程。这也表明了Android系统会对每个APP进行安装前的权限检查,那么我们很自然得要问,如果软件被安装完毕,用户点击了软件图标,或者此软件被启动运行,Android会对运行的程序进行权限检查吗?
二 从一封专家回信谈起
以上是美国安全局Stephen给我的回信,Stephen也是SEAndroid项目的发起人,SEAndroid是2011年发布的开源手机操作系统,它是在Android基础上进行了安全加固,其内核层采用了SELinux,但我要强调的是SEAndroid不等于Android + SELinux,由于本人对SEAndroid认识还比较浅,我画了一个SEAndroid研发流程图,如果不对,请大家指正,
从上图可以看出,SEAndroid非常复杂,但我们此时只讨论Stephen说的权限检查机制。从Stephen的回信可以看出Android的权限检查不是对APP本身,而是系统服务或系统进程,这是如何理解?
三 揭秘Android权限机制
1. Android权限到达是什么?
美国的伯克利大学有一个博士叫Adrienne Porter Felt,她在Android安全方面有着比较高的造诣,目前Adrienne在Google公司工作。在她发表的一篇文章“Android Permissions Demystified”详细阐述了Android权限与Android的JAVA API关系。如果一个APP要想使用Android系统受限资源,比如读写SD卡,那么它必须在自己的manifest.xml文件中声明相应的权限,如<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE/>。一个权限一般是与Android的JAVA API对应,而且是多对多的关系,如下图:
而API调用又可以被分为三步,第一,应用程序获取相应权限后会调用公共库中的API,第二,公共API会调用一个叫API代理的接口(RPC stub),第三,此接口把请求传递给系统服务,由系统服务进程完成具体的功能。如下图所示:
权限检查恰恰发生在对系统服务和系统进程中。
2. Android系统完成权限检查的代码在哪?
打开Android系统框架层源码,切换到ActivityManagerService,java和PackageManagerService.java,在这两个文件中,有关于权限检查的代码,其中checkComponentPermissions在ActivityManagerService.java中,它会调用PackageManagerService.java中的checkUidPermission。如下图所示:
当一个APP的activity从开始到主界面显示之间,ActivityManagerService会对其进行权限检查,当主界面出现后,PackageManagerService会对应用程序调的系统进程进行权限检查,因此,Android系统既存在安装时的权限检查,又存在程序运行时的权限检查。
四 RBAC解决方案
RBAC是上世纪70年代出现的一种简化权限管理的安全模型,目前已经在商业上取得了一定的成功,有着大量成熟的RBAC产品。RBAC(Role based Access Control)是一种基于角色的强制访问控制模型,它利用角色简化权限,当被用于商业系统管理时,权限不在直接分配给用户,而是安全管理员根据安全需求,设计出合适的角色,每种角色代表一定的权限,用户只有获取角色,才能行使一定的权限。下图是我开发出的简化版的Android RBAC系统:
这个系统包含五个模块,其实这五个模块是用户操作RBAC数据库的接口,RBAC数据库放在Android框架层,这也是出于效率的考虑。每当用户安装完了某款Android应用程序,那么此应用程序就成为了Android系统的一个用户,有着唯一的UID,这个UID是链接到Linux内核的进程UID。我们大家都玩过Android游戏,但很多恶意代码是嵌入到游戏中去的,它们会利用已经被用户批准的权限进行破坏活动,那么我们就可以利用这个我开发的这个系统对其进行管理和限制。
五 系统功能简易测试
为了验证系统的功能,我们选择一款Android模拟器上的游戏软件cheeseTower:
这个软件已经被安装成功了,我们查看它的权限,发现如下:
Android系统批准了网络通信和读取电话两项权限,这也是cheeseTower在自己manifest文件中声明的权限需求。我在PackageManagerService中做了数据库,记录了当checkUidPermission(int uid, String permName)中每个uid和相应的权限名。我们切换到adb shell,利用sqlite3打开rbac.db,查看相应的表,记录显示如下:
这里的uid=10035是我开发的RBAC系统中可以查看到的,我们发现,cheeseTower在运行时要求了过多的权限,即访问粗细位置。需要强调的是,有些权限是软件要想运行起来所必须的,cheeseTower要想运行起来,读电话状态和访问无线是必须的,而且cheeseTower正是通过访问wifi来连接网络的。
这样,我们利用RBAC系统新建一个game角色,并为它只分配读电话状态权限,如下图:
好了,我们角色新建就完成了,那么Android框架层RBAC控制代码就可以依据我们刚才建立的数据进行访问控制了。但值得注意的是,cheeseTower要想被Laucher启动起来出现主界面,必须获取读电话和访问wifi权限,我们没有分配给其启动时足够的权限,如果此时点击它的图标,会出现cheeseTower has stopped的提示,cheeseTower启动终止了。还记得我上面画的访问控制图吗,我对于启动Activity做了修改,让Launcher在启动应用程序时忽略RBAC访问控制,好的,以下的实验如下图:
从实验效果看,我们已经能够阻止cheeseTower连入网络,如果你回到RBAC管理系统,更改角色,不分配game访问wifi权限,而是访问Internet权限,cheeseTower仍然无法连入网络。我们进入修改角色模块,为game分配访问wifi权限,这样,cheeseTower可以连入网络了,如下图:
六 接下来的工作
其实,我们不仅仅要拒绝应用程序使用某种权限,而且要能够在某种条件下拒绝权限,或者应用程序在什么样的条件下可以使用权限,使用权限能够做哪些事情。举个很简单例子,很多软件都要求访问网络权限,而恶意软件恰恰是利用此对Android系统进行远程监控或恶意扣费等。我们可以批准应用程序上网的权限,但我们能够限制应用程序可以访问站点的范围,比如我们可以建立白黑名单制度,再如发短信,我们可以指定应用程序向哪些号码发送短信,而这些工作难度确实比较大,我还在继续研究中。