Android(十)SEAndroid初探
0x1 SEAndroid简介
SEAndroid(Security-Enhanced Android),是将原本运用在Linux操作系统上的MAC强制存取控管套件SELinux,移植到Android平台上。可以用来强化Android操作系统对App的存取控管,建立类似沙箱的执行隔离效果,来确保每一个App之间的独立运作,也因此可以阻止恶意App对系统或其它应用程序的攻击。
SEAndroid在架构和机制上与SELinux完全一样,中心理念为:即使恶意应用获取了root权限,依然可以阻止应用的越权读取行为。考虑到移动设备的特点,所以移植到SEAndroid的只是SELinux的一个子集。
0x2 SEAndroid策略
SEAndroid是一种基于安全策略的MAC安全机制。这种安全策略又是建立在对象的安全上下文的基础上的。这里所说的对象分为两种类型,一种称主体(Subject),一种称为客体(Object)。主体通常就是指进程,而客观就是指进程所要访问的资源,例如文件、系统属性等。
SEAndroid的安全检查覆盖了所有重要的方面包括了域转换、类型转换、进程相关操作、内核相关操作、文件目录相关操作、文件系统相关操作、对设备相关操作、对app相关操作、对网络相关操作、对IPC相关操作。
在用户空间中,SEAndroid包含有三个主要的模块,分别是安全上下文(Security Context)、安全策略(SEAndroid Policy)和安全服务(Security Server)。
0x21 SEAndroid工作模式
目前 SELinux 支持三种模式,分别如下:
- enforcing:强制模式,代表 SELinux 运行中,且已经正确的开始限制 domain/type 了;
- permissive:宽容模式:代表 SELinux 运行中,不过仅会有警告信息并不会实际限制 domain/type 的存取,这种模式可以运来作为 SELinux 的 debug 之用;
- disabled:关闭,SELinux 并没有实际运行。
显示SEAndroid工作状态可以使用以下指令,输出结果为
Enforcing
,说明使用强制模式:$ getenforce
Enforcing
设置SEAndroid工作模式可以使用以下指令,enforcing为1,permissive为0,但需要相应权限才能执行:
$ setenforce --help
usage: setenforce [enforcing|permissive|1|0]
Sets whether SELinux is enforcing (1) or permissive (0).
$ setenforce 1
setenforce: Could not set enforcing status to '1': Permission denied
$ setenforce 0
setenforce: Could not set enforcing status to '0': Permission denied
0x22 安全上下文(Security Context)
SEAndroid的安全上下文与SELinux基本一致,实际上就是一个附加在对象上的标签(Tag)。这个标签实际上就是一个字符串,它由四部分内容组成,分别是SELinux用户、SELinux角色、类型、安全级别,每一个部分都通过一个冒号来分隔,格式为
user:role:type:sensitivity
。
通过
ls -Z
指令可以查看文件的安全上下文信息:
1|sailfish:/ $ ls -Z
u:object_r:cgroup:s0 acct u:object_r:tmpfs:s0 mnt
u:object_r:rootfs:s0 bin u:object_r:vendor_file:s0 odm
u:object_r:rootfs:s0 bugreports u:object_r:oemfs:s0 oem
u:object_r:rootfs:s0 charger u:object_r:proc:s0 proc
u:object_r:configfs:s0 config u:object_r:system_file:s0 product
u:object_r:rootfs:s0 d u:object_r:rootfs:s0 res
u:object_r:system_data_file:s0 data u:object_r:rootfs:s0 sbin
u:object_r:rootfs:s0 default.prop u:object_r:rootfs:s0 sdcard
u:object_r:device:s0 dev u:object_r:storage_file:s0 storage
u:object_r:rootfs:s0 dsp u:object_r:sysfs:s0 sys
u:object_r:rootfs:s0 etc u:object_r:system_file:s0 system
u:object_r:firmware_file:s0 firmware u:object_r:vendor_file:s0 vendor
u:object_r:rootfs:s0 lost+found
通过
ps -Z
指令可以查看进程的安全上下文信息:
sailfish:/ $ ps -Z
LABEL USER PID PPID VSZ RSS WCHAN ADDR S NAME
u:r:shell:s0 shell 8987 8920 9256 1988 SyS_rt_si+ 7c60833e58 S sh
u:r:shell:s0 shell 9666 8987 11724 2200 0 7192d327b8 R ps
以
u:object_r:system_data_file:s0
为例,这些标记代表含义如下:- user:安全上下文的第一列为SELinux用户,在SEAndroid中的user只有一个就是u。
- role:第二列表示SELinux角色,在SEAndroid中的role有两个,分别为r和object_r。
- type:第三列为type类型,SEAndroid中共定义了139种不同的type。
- security level:第四列为安全级别,由敏感性(Sensitivity)和类别(Category)两部分内容组成的,格式为
sensitivity[:category_set]
,category_set
可选。
安全上下文中最重要的部分就是第三列的type,type是整个SEAndroid中最重要的一个参量,所有的policy都围绕这一参量展开,所以为系统中每个文件标记上合适的type就显得极为重要。而SELinux用户、SELinux角色和安全级别都几乎可以忽略不计的。
在SEAndroid中,我们通常将用来标注文件的安全上下文中的类型称为file_type,而用来标注进程的安全上下文的类型称为domain,并且每一个用来描述文件安全上下文的类型都将file_type设置为其属性,每一个用来进程安全上下文的类型都将domain设置为其属性。
0x23 SEAndroid配置文件
四种类型的对象的安全上下文,分别是App进程、App数据文件、系统文件和系统属性。这四种类型对象的安全上下文通过四个文件来描述:mac_permissions.xml、seapp_contexts、file_contexts和property_contexts,这几个文件通常在
/sys/fs/selinux
(早期版本)或/etc/selinux/
目录下:
$ ls -ahlZ
ls: ./plat_hwservice_contexts: Permission denied
ls: ./plat_mac_permissions.xml: Permission denied
total 536K
drwxr-xr-x 3 root root u:object_r:system_file:s0 4.0K 2009-01-01 16:00 .
drwxr-xr-x 17 root root u:object_r:system_file:s0 4.0K 2009-01-01 16:00 ..
drwxr-xr-x 2 root root u:object_r:system_file:s0 4.0K 2009-01-01 16:00 mapping
-rw-r--r-- 1 root root u:object_r:sepolicy_file:s0 65 2009-01-01 16:00 plat_and_mapping_sepolicy.cil.sha256
-rw-r--r-- 1 root root u:object_r:file_contexts_file:s0 23K 2009-01-01 16:00 plat_file_contexts
-rw-r--r-- 1 root root u:object_r:property_contexts_file:s0 6.5K 2009-01-01 16:00 plat_property_contexts
-rw-r--r-- 1 root root u:object_r:seapp_contexts_file:s0 1.2K 2009-01-01 16:00 plat_seapp_contexts
-rw-r--r-- 1 root root u:object_r:sepolicy_file:s0 0.9M 2009-01-01 16:00 plat_sepolicy.cil
-rw-r--r-- 1 root root u:object_r:service_contexts_file:s0 14K 2009-01-01 16:00 plat_service_contexts
0x3 规则分析
AOSP提供的所有Android策略文件都在源码路径external/sepolicy目录下面,在编译完成之后一共会生成如下个module:
0x31 sepolicy
sepolicy 其主要用于配置进程的安全上下文用来控制进程访问内核资源(文件,端口等等)策略和设置虚拟文件系统的安全上下文,系统启动之后,会由init进程在
/sys/fs /selinux
中安装一个selinux虚拟文件系统,接着再加载SEAndroid安全策略到内核空间的selinux lsm模块中去。
sepolicy文件其实就是SEAndroid的安全策略配置文件,里面有所有进程的权限配置,进程只能进行它的权限规定内的操作。这个文件root权限也删不掉,把这个文件的内容dump出来后会发现里面有好多条规则,看两条例子:
allow untrusted_app system_app_data_file : file { read }
allow zygote sdcard_type : file { read write creat rename }
它的具体格式为:
通过这个格式解读上面的两条规则就是:
allow Domain Type : Class { Permission }
(Domain 是指进程的type)通过这个格式解读上面的两条规则就是:
- 允许 untrusted_app类型的进程对 system_app_data_file类型的文件进行read。
- 允许zygote类型的进程对sdcard_type的file进行 read write creat rename。
所以MAC控制方式是这个样子的:
当一个进程去操作一个文件的时候,系统会去检测这个进程和文件的上下文,看看这个进程的所属的type有没有对这个的文件的type操作的权限。比如:zygote如果要去读sdcard上的一个文件,这个文件的type为sdcard,zygote的type(Domain)为zygote, 系统去检测看看发现这条规则
当一个进程去操作一个文件的时候,系统会去检测这个进程和文件的上下文,看看这个进程的所属的type有没有对这个的文件的type操作的权限。比如:zygote如果要去读sdcard上的一个文件,这个文件的type为sdcard,zygote的type(Domain)为zygote, 系统去检测看看发现这条规则
allow zygote sdcard_type : file { read write creat rename }
。那么这个操作就会被允许执行。zygote要是想删除一个sdcard上的文件,系统发现对应的规则里没有delete,那么就会被deny。0x32 file_contexts
file_contexts模块用于设置打包在ROM里面的文件的安全上下文。其是由
external/sepolicy/file_contexts
文件编译而成。
例如在
build systemimage
时会将这个file_contexts文件路径传递给命令make_ext4fs时,就会根据它设置的规则给打包在 system.img里面的文件关联安全上下文。这样就获得了一个关联有安全上下文的system.img镜像文件了。
通过fastboot命令将system.img刷入system分区mount到/system目录之后,因为设置了相应的安全上下文,这样就能控制进程访问system目录下相关文件.
0x33 seapp_contexts和mac_permissions.xml
seapp_contexts
是负责设置APP数据文件的安全上下文,mac_permissions.xml
是负责设置APP进程的安全上下文.路径:
external/sepolicy/mac_permissons.xml
文件
mac_permissions.xml
给不同签名的App分配不同的seinfo字符串,例如,在AOSP源码环境下编译并且使用平台签名的App获得的seinfo为“platform”,使用第三方签名安装的App获得的seinfo签名为”default”。这个seinfo描述的是其实并不是安全上下文中的Type,它是用来在另外一个文件seapp_contexts中查找对应的type的。路径:
external/sepolicy/seapp_context
sisSystemServer=true domain=system_server
user=system domain=system_app type=system_app_data_file
user=bluetooth domain=bluetooth type=bluetooth_data_file
user=nfc domain=nfc type=nfc_data_file
user=radio domain=radio type=radio_data_file
user=shared_relro domain=shared_relro
user=shell domain=shell type=shell_data_file
user=_isolated domain=isolated_app
user=_app seinfo=platform domain=platform_app type=app_data_file
user=_app domain=untrusted_app type=app_data_file
例如,于使用平台签名的App来说,它的seinfo为
platform
。用户空间的SecurityServer(比如installd)在为它查找 对应的Type时,使用的user输入为_app
。这样在seapp_contexts
文件中,与它匹配的一行即为:user=_app seinfo=platform domain=platform_app type=app_data_file
这样就可以知道,使用平台签名的App所运行在的进程domain为platform_app
,并且它的数据文件的file_type
为app_data_file
。0x34 property_contexts
在Android系统中,有一种特殊的资源——属性,App通过读写它们能够获得相应的信息,以及控制系统的行为,因此,SEAndroid也需要对它们进行保护。这意味着Android系统的属性也需要关联有安全上下文。
路径:external/sepolicy/property_contexts
路径:external/sepolicy/property_contexts
##########################
# property service keys
#
#
net.rmnet u:object_r:net_radio_prop:s0
net.gprs u:object_r:net_radio_prop:s0
net.ppp u:object_r:net_radio_prop:s0
...
属性的安全上下文与文件的安全上下文是类似的,将属性
net.rmnet
设置为u:object_r:net_radio_prop:s0
, 意味着只有有权限访问type为net_radio_prop的资源的进程才可以访问这个属性。0x35 service_contexts
在AndroidL系统中,还将服务(属于进程或线程)也作为一种资源来定义,给其定义对应的安全上下文,用来保护服务不被恶意进程访问.
路径:
路径:
external/sepolicy/service_contexts
...
window u:object_r:system_server_service:s0
* u:object_r:default_android_service:s0
服务的安全上下文同样与文件的安全上下文是类似的,将window服务设置为u:object_r:system_server_service:s0,意味着只有有权限访问type为system_server_service的资源的进程才可以访问这个服务。
0x4 攻击案例
0x41 绕过SEAndroid几个方法
由于SELinux引入android不久,还有很多不完善的地方。在DEFCON 21上,来自viaForensics的Pau Oliva就演示了几个方法来绕过SEAndroid:
- 用恢复模式(recovery)刷回permissive模式的镜像
- Su超级用户没有设置SELinux模式权限,但是system user系统用户可以。
- Android通过/system/app/SEAndroidManager.apk来设置SELinux模式,所以只要在recovery模式下将其删除就可以绕过
- 在Android启动时直接操作内核内存,通过将内核里的unix_ioctl符号改写成reset_security_ops重置LSM(Linux Security Modules)
0x42 Fastboot 中将SELinux 更改为 Permissive 模式
这个问题是一加手机 3/3T Bootloader 漏洞,允许在 Fastboot 中将SELinux 更改为 Permissive 模式。
fastboot oem selinux permissive
...
OKAY [ 0.045s]
finished. total time: 0.047s
....
OnePlus3:/ $ getenforce
Permissive
OnePlus3:/ $
0x5 参考
一加手机 3/3T Bootloader 存在漏洞(允许在 Fastboot 中将SELinux 更改为 Permissive 模式)