Android是一个开放的移动设备操作系统。根据 IDC 2013年11月份的数据统计[1],Android 手机的市场份额为80%。丰富的Android应用程序(简称应用)极大方便了我们的生活,同时系统的安全性也越来越引起用户的关注。Android应用可以操作设备上的各种硬件、软件以及本地数据和服务器数据,并能够访问网络。因此,Android操作系统为了保护数据、程序、设备和网络等资源,必须为程序提供一个安全的运行环境 。该文首先介绍Android安全体系结构,然后重点介绍系统内核层的采用的安全技术和应用框架层为开发者开发安全的应用程序提供的各种安全措施。该文为程序开发人员了解系统安全及开发安全应用提供有用的参考。
1 Android安全体系结构
操作系统的安全性目的就是为了保护移动设备软件、硬件资源,包括CPU、内存、外部设备、文件系统和网络等。Android系统为了安全性,提供如下主要安全特征:操作系统严格的分层结构、应用沙盒、安全进程通信、授权和签名等。Android作为开放平台,它的设计和实现细节完全暴露,因此对安全性要求更加严格,设计时首先要重点考虑的就是平台结构设计问题, Android系统的体系结构设计为多层结构[2],如图1所示。这种结构在给用户提供安全保护的同时还保持了开放平台的灵活性。
图1 Android操作系统分层的安全体系结构
Android系统结构由4层组成,从上到下分别是: 应用层(Applications)、应用框架层(Application Framework)、运行时(Android Runtime)、类库层(Libraries)和Linux内核(Linux Kernel)组成。应用层由运行在Android设备上的所有应用构成,包括预装的系统应用和用户自己安装的第三方应用。大部分应用是由Java语言编写并运行在Dalvik虚拟机中;另一部分应用是通过C/C++语言编写的本地应用。不论采用何种编程语言,两类应用运行的安全环境相同,都在应用沙箱中运行。应用框架层集中体现Android系统的组件设计思想。框架层由多个系统服务(System Service)组成。Android应用由若干个组件构成,组件和组件之间的通信是通过框架层提供的服务集中调度和传递消息实现的,而不是组件之间直接进行的。框架层协调应用层的应用工作提升了系统的整体安全性。类库层主要由类库和Android运行时两部分组成。其中类库由一系列的二进制动态库构成,大部分来源于优秀的第三方类库,另一部分是系统原生类库;通常使用C/C++语言开发。Android运行时由Java核心类库和Android虚拟机Dalvik共同构成。Java核心类库包括框架层和应用层所用到基本Java库。Dalvik是为Android量身打造的Java虚拟机,它与标准 Java 虚拟机(JVM)主要差别在于Dalvik是基于寄存器设计的,而JVM是基于数据栈的,前者能够更快的编译较大的应用程序。Dalvik允许在有限的内存中同时运行多个虚拟机的实例,每一个 Dalvik 应用作为一个独立的 Linux 进程执行,可防止在某一虚拟机崩溃时所有应用都被关闭。最后一层是Linux内核层,该层提供核心系统服务包括安全、内存、进程、网络和设备驱动等功能。
2 系统内核安全
在操作系统层Android充分利用已有的Linux内核安全机制,并在此基础上进行改进如应用沙盒和安全IPC(inter-process communication,进程通信),这些安全机制可以保证即使本地代码程序也被限制在应用沙盒中安全运行。
2.1 Linux安全性
Android平台的基础是Linux内核。Linux操作系统经过多年的发展,已经成为一个稳定的安全的被许多公司和安全专家信任的安全平台[3]。作为移动平台的基础,Linux内核为Android提供了如下安全功能:基于用户授权的模式、进程隔离、可扩展的安全IPC和移除不必要的不安全的内核代码。作为多用户操作系统,Linux内核提供了相互隔离用户资源的功能。通过隔离功能,一个用户不能使用另一个用户的文件、内存、CPU和设备等。
2.2 应用沙盒
Android平台把Linux基于用户的授权模式作为标识和隔离应用程序资源的方式。系统为每个应用分配一个用户ID(UID), 并在该设备上一直保持这个数值;运行时,把应用当作编号为UID的用户在一个单独的进程运行。简而言之,Android系统中一个UID对应一个进程。这一点与其它操作系统不同,在其它操作系统中,一个UID可以拥有多个进程。Android采用这种方式作为内核层的应用沙盒(Application Sandbox)。通过分配UID给应用程序这种方式,增强了系统的安全性。默认情况下,应用之间不能相互操作,应用访问操作系统的功能也受到限制。例如,在没有授权的情况下应用A想要读取应用B的数据或想要使用电话功能都会被操作系统拒绝。由于应用沙盒位于内核层,所以这种安全模式可以作用到图1所示的Linux内核之上的所有层。在有的平台上,为了增强安全性,开发者被限制在指定的开发框架、API集或开发语言上。但在Android平台中,采用C/C++与采用Java编写的应用其安全性都一样,因为最终都运行在沙盒中。在有的操作系统中内存错误会导致系统安全性降低。但在Android中由于应用及其数据存在于沙盒中,内存错误至多影响当前应用而不会影响其它应用。
2.3 文件系统许可/加密
在Linux环境中,文件系统许可(permission )可以保证一个用户不能修改或读取另一个用户的文件。Android系统中每个应用都分配一个用户ID,应用作为一个用户存在,因此除非开发者明确指定某文件可以供其它应用访问,否则一个应用创建的文件其它应用不能读取或修改。 文件系统加密功能可以对整个文件系统进行加密。内核利用dm-crypt技术创建加密文件系统 。dm-crypt技术是建立在Linux 内核2.6版本的device-mapper特性之上的。 device-mapper是在实际的块设备之上虚拟层可以方便开发人员实现镜像、快照、级联和加密等处理。为了防止系统口令攻击(例如通过彩虹表或暴力破解等方法),口令采用SHA1加密算法进行保存。为了防止口令字典攻击,系统提供口令复杂性规则,规则由设备管理员制定,由操作系统实施。
2.4 其它
内核安全措施还包括丰富的数据加密函数、内存安全管理增强、刷机时保护用户数据等。Android系统为应用开发提供了一组实现加密功能的API函数,包括标准的加密算法[4]如AES, RSA, DSA, 和 SHA等;及更高层的安
全网络协议如SSL 和 HTTPS。据统计,操作系统中超过50%的安全漏洞都是由内存溢出引起的。为此,Android系统提供的SDK、编译器和工具可以增强保护内存的力度,更大程度防止内存溢出。随着更高版本的Android系统推出,内存管理的功能也不断增强,包括ProPolice 、safe_iop 、增强的dlmalloc 、Address Space Layout Randomization (ASLR) 、PIE (Position Independent Executable)、dmesg_restrict 等。其中ASLR是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。ASLR可以有效的降低缓冲区溢出攻击的成功率。
3 Android应用安全
Android系统为移动设备提供了一个开源的平台和应用程序开发环境。通常程序开发语言采用Java,并运行在Dalvik虚拟机中,对于游戏等性能要求较高的程序也可以采用C/C++编写。程序安装包以.apk为扩展名。一个应用程序通常由配置文件(AndroidManifest.xml)、活动(Activity)、服务(Service)和广播接收器(Broadcast Receiver)组成等组成。
3.1 Android权限模式
所有的应用程序都运行在应用沙盒中,默认情况下,应用只能存取受限的系统资源。这种受限机制的实现方式有多种,包括不提供获取敏感功能的API函数、采用角色分离技术和采用权限模式。权限模式最常用,通过这种方式把用于存取敏感资源的API函数只授权给值得信任的应用程序,这些函数主要涉及的功能包括摄像头、GPS、蓝牙、电话、短信和网络等。应用程序为了能够存取这些敏感资源,必须在它的配置文件中声明存取所需资源的能力。当用户安装这种程序时,系统会显示对话框提示程序需要的权限并询问用户是否需要继续安装。如果用户继续安装,系统就把这些权限授予对应的程序。安装过程中,针对用户只想授权其中的某些权限的情况系统是不支持的。 安装完毕后,用户可以通过“系统设置”功能允许或拒绝某些权限。对于系统自带的应用程序,系统不会提示请求用户授权。如果程序的配置文件中没有指定受保护资源的授权,但程序中调用了资源对应的API函数,则系统抛出安全异常。程序的配置文件中还可以定义安全级别(protectionLevel )属性,这个属性告诉系统其它哪些应用可以访问此应用。
3.2 安全进程通信
尽管Linux内核提供了多种进程通信(IPC)机制,包括管道、信号、报文、信号量、共享内存和套接字等。但出于安全性考虑Android增加了新的安全IPC机制,主要包括Binder、Service,Intent和ContentProvider。Binder是一个轻量级的远程过程调用机制,它可以高效安全地实现进程内和进程间调用[5]。Service运行在后台并通过Binder向外提供接口服务,通常不具有可见的用户界面。Intent是一个简单的消息对象,此对象表示想要做某事的“意向”。ContentProvider是一个数据仓库,通过它可以向外提供数据。例如一个程序可以获取另一个应用通过ContentProvider向外公布的数据。在编写程序时如果需要进程通信,虽然可以使用Linux提供的传统的方式,但还是推荐使用Android提供的安全IPC框架,这样可以避免传统方式存在的通信安全缺陷。
3.3应用程序安装包签名
所有的 Android 应用程序安装包(apk 文件)必须进行签名,否则程序不能安装在Android设备或模拟器中。签名的目的用于标识程序作者、升级应用程序。当没有签名的应用在安装时,包管理器就会拒绝安装。签名的应用在安装时,包管理器首先验证APK文件中的签名证书是否正确,如果正确,首先把应用放置在应用沙盒中,然后系统为它分配一个UID,不现的应用有不同的UID;如果证书签名与设备中其它签名的应用相同,表示是同一个应用,则提示用户是否用新的应用更新老的相应。该签名证书可以由开发者自己设定称之为自签名(self-signed)证书,也可以由第三方的认证机构授权。系统提供自签名证书功能使得开发者不再需要借助外部的帮助或授权即可以自己进行签名。Google公司提供了完整方便的签名工具为用户开发提供便利。
4 结论
Android系统作一个安全开源的移动平台,在系统内核层次与应用开发方面都提供了强大的安全措施。在系统内核层次,应用沙盒可以实现应用之间的隔离,防止一个应用的数据和代码被其它没有授权的应用存取;随着系统版本的升级,内存管理功能随之丰富;加密的文件系统可以保护丢失设备上的数据不被泄漏。在应用开发方面同,采用加密、授权和安全IPC等措施构建的应用程序框架具有强大的安全特性;授权模式可以限制应用对系统功能和用户数据的存取;应用指定的权限级别可以控制其它应用对自己的访问;数字签名保证了程序开发者与应用之间的信任关系。Android在安全性设计方面还考虑了尽量减少应用开发人员的负担问题。针对安全性要求高的开发者通过平台提供的灵活的安全控制机制可以轻松开发应用程序。针对安全性要求不高的开发者,系统默认的安全措施也能够对应用程序提供较好的保护。对于可能存在的恶意攻击,系统提供了防范机制,一方面降低攻击成功的概率,另一方面尽量限制攻击后系统所受损失。
参考文献:
[1] Android手机市场份额首次超过80% [EB/OL]. [2014-1-25].http://mobile.yesky.com/414/35414414.shtml.
[2] Google Inc. Security Tips[EB/OL].[2013-10-20].https://developer.android.com/training/articles/security-tips.html.
[3] 柯元旦. Android内核剖析[M].北京:电子工业出版社,2011.
[4] (美)Christian Collberg Jasvir Nagra.软件加密与解密[M].崔孝晨,译.北京:人民邮电出版社,2012.