前言:
尽管 Android这个词仍然可以用来指代人形机器人,但如今其含义已经远比十年前丰富,可以用于许多种场景中。在移动领域中,它既可以指公司、操作系统,也可以指开源项目和开发者社区。一些人甚至把移动设备称为Android。总之,现在围绕着这个非常流行的移动操作系统,已经形成了一个完整的生态圈。
随着 Android的成长,基于Android操作系统的设备数量也随之增长。在过去的几年里,Android已经缓慢地从传统的智能手机和平板电脑市场往外扩张,进入最不可能的领域中。例如,智能手表、电视机配件、游戏主机、烤箱、发送到太空中的卫星,以及新的Google Glass(具有头戴式显示屏的可穿戴设备)等设备都是由Android系统支持的。汽车产业也开始使用 Android 作为车辆信息娱乐系统。这款操作系统也开始在嵌入式Linux领域中站稳脚跟,成为对嵌入式开发者非常有吸引力的替代方案。所有这些都将让Android设备家族成为一个非常多样化的领域。
Android的安全设计与架构
Android系统由许多承担安全检查与策略执行任务的机制构成。与任何现代操作系统一样,Android中的这些安全机制互相交互, 交换关于主体(应用、用户) 、客体(其他应用、文件和设备)以及将要执行操作(读、写、删除等)的各种信息。安全策略执行通常不会发生故障,但偶尔也会出现一些裂缝, 为滥用提供了机会。本文将讨论Android系统的安全设计与架构, 为分析Android平台的整体攻击面打好基础。
理解Android系统架构
Android的总体架构有时被描述为“运行在Linux上的Java”,然而这种说法不够准确,并不能完全体现出这一平台的复杂性和架构。Android的总体架构由5个主要层次上的组件构成,这5层是: Android应用层、Android框架层、Dalvik虚拟机层、用户空间原生代码层和Linux内核层。下图显示了这些层是如何构成Android软件栈的。
Android系统中的用户空间原生代码组件包括系统服务(如vold和DBus)、网络服务(如dh 和wpa_supplicant)和程序库(如bionic libc、WebKit和OpenSSL)。其中一些服务和程序库会与内核级的服务与驱动进行交互,而其他的则只是便利底层原生操作管理代码。
Android的底层基础是Linux内核,Android对内核源码树作了大量的增加与修改,其中有些代码存在一些独特的安全后果。
内核级驱动也提供了额外的功能,比如访问照相机、Wi-Fi以及其他网络设备。需要特别注意Binder驱动,它实现了进程间通信(IPC)机制。
理解安全边界和安全策略执行
安全边界,有时也会称为信任边界,是系统中分隔不同信任级别的特殊区域。一个最直接的例子就是内核空间与用户空间之间的边界。内核空间中的代码可以对硬件执行一些底层操作并访问所有的虚拟和物理内存,而用户空间中的代码则由于CPU的安全边界控制,无法访问所有内存。
Android操作系统应用了两套独立但又相互配合的权限模型。在底层, Linux内核使用用户和用户组来实施权限控制,这套权限模型是从 Linux继承过来的,用于对文件系统实体进行访问控制,也可以对其他 Android特定资源进行控制。这一模型通常被称为 Android沙箱。以 Dalvik vm 和 Android框架形式存在Android运行时实施了第二套权限模型。这套模型在用户安装应用时是向用户公开的,定义了应用拥有的权限,从而限制 Android应用的能力。事实上,第二套权限模型中的某些权限直接映射到底层操作系统上的特定户、用户组和权能( Capability)
Android沙箱
Android从其根基Linux继承了已经深入人心的类Unix进程隔离机制与最小权限原则。具体而言,进程以隔离的用户环境运行,不能相互干扰,比如发送信号或者访问其他进程的内存空间。
因此,Android沙箱的核心机制基于以下几个概念:标准的Linux进程隔离、大多数进程拥有唯一的用户ID(UID),以及严格限制文件系统权限。
Android IDX AID)的映射表。初始的AID映射表包含了一些与特权用户及系统关键用户(如system 用户/用户组)对应的静态保留条目。Android还保留了一段AID范围,用于提供原生应用的UID.
Android 4.1之后的版本为多用户资料档案和隔离进程用户增加了额外的AID范围段(如Chrome 沙箱),你可以从AOSP树的system/core/include/private/android filesystem config.h文件中找到AID的定义。以下是一个简化过的示例。
除了AID,Android还使用了辅助用户组机制,以允许进程访问共享或受保护的资源。例如,sdcard_rw用户组中的成员允许进程读写/sdcard目录,因为它的加载项规定了哪些用户组可以读写该目录。这与许多Linux发行版中对辅助用户组机制的使用是类似的。
**注意:**除了AID,Android还使用了辅助用户组机制,以允许进程访问共享或受保护的资源。例如,sdcard_rw用户组中的成员允许进程读写/sdcard目录,因为它的加载项规定了哪些用户组可以读写该目录。这与许多Linux发行版中对辅助用户组机制的使用是类似的。
除了用来实施文件系统访问,辅助用户组还会被用于向进程授予额外的权限。例如,AID_INET用户组允许用户打开AF_INET和AF_INET6套接字。在某些情况下,权限也可能以Linux权能的形式出现,例如,AID_INET_ADMIN用户组中的成员授予CAP_NET_ADMIN权能,允许用户配置网络接口和路由表。本节最后还会介绍与网络相关的其他相似用户组。
注意:对Linux权能的完整讨论已经超出了本章的范围。你可以分别从Linux内核的Documentation/security/credentials.txt文档和capabilities的用户手册页面获得更多关于Linux进程安全和Linux权能的信息。
在应用执行时,它们的UID、GID和辅助用户组都会被分配给新创建的进程。在一个独UID和GID环境下运行,使得操作系统可以在内核中实施底层的限制措施,也让运行环境能够控制应用之间的交互。这就是Android沙箱的关键所在。
下面的代码给出了在一台HTCOneV手机上运行ps命令后的输出结果,注意,最左侧显示的UID对于每个应用的进程都是独特的。
通过使用应用包中的一种特殊指令,应用也可以共享UID,这一点我们会在以后详细讨论。 实际上,进程显示的用户与用户组名称是由一种poSIx函数的Android专有实现所提供的,这种函数通常就是用来设置和获取这些值的。例如,考虑在Bionic库的stubs.cpp文件中定义的getpwuid函数。
与它的同胞函数一样,getpwuid函数会调用一些额外的Android专有函数,如android_idto passwd()和app_id_to_passwd()函数。这些函数会把Unix的口令结构填充上相应的AID映射信息表。androididto passwd()函数会调用android_iinfo_to passwd()函数来完成这一替换。
Android权限
Android的权限模型是多方面的,有API权限、文件系统权限和 IPC权限。在很多情况下,这些权限都会交织在一起。正如前面提到的,一些高级权限会后退映射到低级别的操作系统权能,这可能包括打开套接字、蓝牙设备和文件系统路径等。
要确定应用用户的权限和辅助用户组,Android系统会处理在应用包的AndroidManifest.xml 文件中指定的高级权限(Manifest文件和权限会在 2.3.1 节详细描述)。应用的权限由PackageManager在安装时从应用的Manifest文件中提取,并存储在/data/system/packages.xml文件中。这些条目然后会在应用进程的实例化阶段用于向进程授予适当的权限(比如设置辅助用户组GID)。下面的代码片段显示了packages.xml文件中的Chrome浏览器条目,包括这个应用的唯一UID以及它所申请的权限。
在应用包条目中定义的权限后面会通过两种方式实施检查:一种检查在调用给定方法时进行,由运行环境实施;另一种检查在操作系统底层进行,由库或内核实施。
API权限
API权限用于控制访问高层次的功能,这些功能存在于 Android API、框架层,以及某种情况下的第三方框架中。一个使用API权限的常见例子是READ_PHONE_STATE,这个权限在Android 文档中定义为允许“对手机状态的只读访问”。应用若申请该权限,随后就会授予该权限,从而可以调用关于查询手机信息的多种方法,其中包括在TelephonyManager类中定义的方法,如getDeviceSoftwareVersion和getDeviceid等。
前面提到过,一些API权限与内核级的安全实施机制相对应。例如,被授予 INTERNET权限,意味着申请权限应用的UID将会被添加到inet用户组(GID3003)的成员中。该用户组的成员具有打开 AF_INET和 AF_INET6 套接字的能力,而这是一些更高层次 API功能(如创建HttpURLConnection对象)所必需的。
文件系统权限
Android的应用沙箱严重依赖于严格的Uniⅸx文件系统权限模型。默认情况下,应用的唯UID和GID都只能访问文件系统上相应的数据存储路径。注意,以下代码清单中的UID和GID (分别在第2列和第3列)对于目录都是唯一的,它们的权限被设置为只有这些UD和GID才能问这些目录。
相应地,由这些应用创建的文件也会拥有相应的权限设置。以下代码清单中显示了某个应用的数据目录,子目录和文件的属主和权限都被只设置给该应用的UID和GID。
相应地,由这些应用创建的文件也会拥有相应的权限设置。以下代码清单中显示了某个应用的数据目录,子目录和文件的属主和权限都被只设置给该应用的UID和GID。
这里你可以看到SD卡被使用GID 1015进行挂载,对应为sdcard-rw用户组。应用请求WRITE-EXTERNAL-STORAGE权限后,会将自己的UID添加到这个组中,得到对这一路径的写权限。
IPC权限
IPC权限直接涉及应用组件(以及一些系统的IPC设施)之间的通信,虽然与API权限也有一些重叠。这些权限的声明和检查实施可能发生在不同层次上,包括运行环境、库函数,或直接在应用上。具体来说,这个权限集合应用于一些在Android Binder IPC机制之上建立的主要Android应用组件。关于这些组件和Binder的详细信息,
文木福利:需要【Android攻防学习大纲】的同学请点赞转发后 私信【安卓】
即可免费获得领取方式