概述
通过将传统的操作系统安全控制机制扩展到以下用途,Android 致力于成为最安全、最实用的移动平台操作系统:
- 保护应用和用户数据
- 保护系统资源(包括网络)
- 将应用同系统、其他应用和用户隔离开来
为了实现这些目标,Android 提供了以下关键安全功能:
- 通过 Linux 内核在操作系统级别提供的强大安全功能
- 针对所有应用的强制性应用沙盒
- 安全的进程间通信
- 应用签名
- 应用定义的权限和用户授予的权限
Linux安全
Linux在历经无数攻击以及成千上万的开发者的不断研究和修复之后,其安全性不言而喻,作为移动计算环境的基础,Linux 内核为 Android 提供了一些关键的安全功能,其中包括:
- 基于用户的权限模式
- 进程隔离
- 用于实现安全 IPC 的可扩展机制
- 能够移除内核中不必要的和可能不安全的部分
作为一种多用户操作系统,Linux 内核的一个基本安全目标是将用户资源彼此隔离开来。Linux 的安全理念是防范用户资源之间相互侵扰。因此,Linux 可以:
- 防止用户 A 读取用户 B 的文件
- 确保用户 A 不会占用用户 B 的内存
- 确保用户 A 不会占用用户 B 的 CPU 资源
- 确保用户 A 不会占用用户 B 的设备(例如,电话、GPS、蓝牙)
应用沙盒
Android 平台利用基于用户的 Linux 保护机制来识别和隔离应用资源,可将不同的应用分离开,并保护应用和系统免受恶意应用的攻击。为此,Android 会为每个 Android 应用分配一个独一无二的用户 ID (UID),并在自己的进程中运行。
Android 会使用此 UID 设置一个内核级应用沙盒。内核会在进程级别利用标准的 Linux 机制(例如,分配给应用的用户 ID 和组 ID)实现应用和系统之间的安全防护。 默认情况下,应用不能彼此交互,而且对操作系统的访问权限会受到限制。例如,如果应用 A(一个单独的应用)尝试执行恶意操作,例如在没有权限的情况下读取应用 B 的数据或拨打电话,操作系统会阻止此类行为,因为应用 A 没有适当的用户权限。
由于应用沙盒位于内核层面,因此该安全模型的保护范围扩展到了原生代码和操作系统应用。位于更高层面的所有软件(例如,操作系统库、应用框架、应用运行时环境和所有应用)都会在应用沙盒中运行。
进程间通信
应用签名
SELinux
概述
SELinux:Security-Enhanced Linux,安全增强型 Linux,是一个 Linux 内核模块,也是 Linux 的一个安全子系统。SELinux 主要由美国国家安全局开发,2.6 及以上版本的 Linux 内核都已经集成了 SELinux 模块。
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。
DAC
DAC(Discretionary Access Control,自主式访问控制)。
在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:依据程序的拥有者与文件资源的 rwx 权限来决定有无存取的能力,只要访问这个资源的用户符合以上的条件就可以被访问。
存在的问题:
- root 用户不受任何管制,系统上任何资源都可以无限制地访问。
- 如果不小心将某个目录的权限配置为 777 ,由于对任何人的权限会变成 rwx ,因此该目录的文件就会被任何人所任意存取执行。
MAC
MAC(Mandatory Access Control,委任式访问控制)。
在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。这样一来,即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源。进程的活动空间也可以被压缩到最小。即使是以 root 身份运行的服务进程,一般也只能访问到它所需要的资源。即使程序出了漏洞,影响范围也只有在其允许访问的资源范围内,安全性大大增加。
如此一来,我们针对控制的『主体』变成了『程序』而不是『使用者』了。此外,这个主体程序也不能任意使用系统文件资源,因为每个文件资源也有针对该主体程序配置可取用的权限,如此一来,控制项目就细的多了,但整个系统程序那么多、文件那么多,一项一项控制非常麻烦,所以 SELinux 也提供一些默认的策略 (Policy) ,并在该策略内提供多个rule,让你可以选择是否激活该控制rule。
在委任式存取控制的配置下,我们的程序能够活动的空间就变小了。举例来说,默认情况下,httpd 仅能在 /var/www/ 这个目录底下存取文件,如果 httpd 这个程序想要到其他目录去存取数据时,除了rule配置要开放外,目标目录也得要配置成 httpd 可读取的模式 (type) 才行。所以,即使不小心 httpd 被 cracker 取得了控制权,他也无权浏览 /etc/shadow 等重要的配置档。
运行模式
- 主体 (Subject):SELinux 主要管理的就是程序,即process;
- 目标 (Object):主体程序能否存取的『目标资源』一般就是文件系统;
- 政策 (Policy):由於程序与文件数量庞大,因此 SELinux 会依据某些服务来制订基本的存取安全性政策。这些政策内还会有详细的守则 (rule) 来指定不同的服务开放某些资源的存取与否。
- 安全性上下文 (security context):主体能不能存取目标除了政策指定之外,主体与目标的安全性上下文必须一致才能够顺利存取。这个安全性上下文 (security context) 有点类似文件系统的 rwx 啦,安全性上下文如果配置错误,你的某些服务(主体程序)就无法存取文件系统(目标资源),就会一直出现『权限不符』的错误信息了。
在目前的 CentOS 5.x 里面仅有提供两个主要的政策,分别是:
- targeted:针对网络服务限制较多,针对本机限制较少,是默认的政策;
- strict:完整的 SELinux 限制,限制方面较为严格。
建议使用默认的 targeted 政策即可。
由上图我们可以发现,主体程序必须要通过 SELinux 政策内的守则放行后,就可以与目标资源进行安全性本文的比对,若比对失败则无法存取目标,若比对成功则可以开始存取目标。问题是,最终能否存取目标还是与文件系统的 rwx 权限配置有关,如此一来,加入了 SELinux 之后,出现权限不符的情况时,我们就得要一步一步的分析可能的问题了。
sharedUserId
Android给每个APK进程分配一个单独的空间,manifest中的userid就是对应一个分配的Linux用户ID,并且为它创建一个沙箱,以防止影响其他应用程序(或者其他应用程序影响它)。用户ID在应用程序安装到设备中时被分配,并且在这个设备中保持它的永久性。
通常,不同的APK会具有不同的userId,因此运行时属于不同的进程中,而不同进程中的资源是不共享的,在保障了程序运行的稳定。然后在有些时候,我们自己开发了多个APK并且需要他们之间互相共享资源,那么就需要通过设置shareUserId来实现这一目的。
通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。所以默认就是可以互相访问任意数据。也可以配置成运行成不同的进程,同时可以访问其他APK的数据目录下的数据库和文件。就像访问本程序的数据一样。
用法也很简单:
在需要共享资源的项目的每个AndroidMainfest.xml中添加shareuserId的标签。android:sharedUserId=”com.example”,id名自由设置,但必须保证每个项目都使用了相同的sharedUserId。一个mainfest只能有一个Shareuserid标签。