【总结】SEAndroid/SELinux快速学习

备注

2024/11/18 星期一
在Android安全中,SELinux起着非常重要的保护作用,但是网络上成体系的资料非常稀少和混乱,因此做一个总结

一、背景

Android的系统内核是基于Linux内核修改得到的,Linux内核经典的用户和文件权限管理存在一定的缺陷(root进程不受管控、ugo的划分不够细致、setuid/setgid容易出现提权漏洞、user可以任意修改权限),因此引入了SELinux做为更强的权限管理方式,但是由于Android中的Linux内核经过修改无法直接复用SELinux,Android使用Hook的方式引入LSM模块重新实现了SELinux的功能,由于Android重新实现的SELinux与Linux内核原生SELinux仍然存在部分差异,有时也将Android中的SELinux称为SEAndroid。
Android在Android4.3开始引入SELinux机制,Android4.3采用宽容模式,Android4.4采用部分强制模式,Android5.0及之后的版本都全面采用强制模式,Android6.0、Android7.0分别强化了策略安全性,Android8.0又将SELinux与Treble特性结合。
顺便一提,SEAndroid/SEAndroid机制不是用于减小设备的攻击面的机制,而是在设备受到攻击时降低损害程度。

二、基本概念

1.SEAndroid/SELinux

SELinux是一个复杂的权限管理系统,用于最大限度的保证系统中的进程符合最小权限原则。在SELinux中,Linux经典的权限管理被称为自主访问控制(DAC机制),权限管理的机制的主体是用户,由用户设置权限来保证安全。SELinux权限管理的机制被称为强制访问控制(MAC机制),权限管理的机制的主体是SELinux安全子系统,使用标签和策略来保证安全。SELinux采用白名单机制,只有在策略中明确许可的资源才允许进程访问。MAC机制不会取代DAC机制,Android会在DAC检查通过后再做MAC检查。SELinux的管控会覆盖所有进程,root进程也不例外,这样即使root进程被漏洞攻击,其影响范围也能控制在SELinux允许的范围内,这可以在一定程度上抵御0day漏洞的攻击。

2.状态模式(Enforce Mode)

SELinux的保护模式有三种:

模式作用
关闭模式(Disabled)SELinux子系统处于关闭状态
宽容模式(Permissive)仅记录不符合策略的情况但不强制执行 SELinux 安全政策
强制模式(Enforcing)强制执行安全政策并记录不符合策略的情况

宽容模式一般用于在SELinux策略的开发阶段调试策略编写是否正确。

3.安全标签(Security Context)

SELinux要解决的是一个“Subject是否可以对Object做Action?”的问题,在SEAndroid中,主体(Subject)就是进程,对象(Object)是文件、目录、端口、设备等资源和属性,动作(Action)是读、写、执行等操作。
在SELinux中每个Subject和Object各有自己的Security Context,每个Security Context又分为User、Role、Type、Level四个字段。Subject的Type很多时候也被称为Domain。目前SEAndroid中主要使用了Type字段,少数情况使用了Level字段,User、Role字段暂时可以不关注。基于Type的管理模式称为TEAC模式,这是SELinux最基本的管理模式,基于Level的管理模式称为MLS模式,主要用于有明确上下级的情况。
Security Context的格式为:User:Role:Type:Level

4.安全策略(Policy & Rule)

安全策略是一组规则,用于决定哪些Subject需要管理、要怎么管理,在SELinux中使用.te文件进行保存。策略的格式为:Rule Domain Type : Class Permissions
Rule: 仅有四种

Rule作用
allow赋予某个Domain 对某种Type的Class Permissions权限
neverallow不允许赋予权限,检查策略中是否有和本条冲突的allow语句,如果有生成策略时会失败
allowaudit当操作成功时进行记录
dontaudit当操作失败时不记录

(SELinux默认只记录失败的操作,neverallow和dontaudit只与记录有关不影响权限赋予)
Domain 和Type:
domain和type分别是Subject的Type和Object的Type,实际都是Type。由于Type数量庞大,为了方便管理,SELinux提供了attribute可以将多个type关联到一个attribute中,attribute就是一组type的集合。
Class和Permissions:
class是对Object资源类型的映射,Permissions是某个class的具体的操作权,多个Permissions可以使用{}包裹,要从某些Permissions中去掉某个Permissions可以使用-号。
例如:

allow untrusted_app app_data_file:file { read write };
# 表示带有untrusted_app标签的进程可以读取和写入带有 app_data_file 标签的文件。

5.预定义策略

Android已经在AOSP源码中预先定义了大量的核心策略,并且为了简化策略编写提供了宏,Android建议尽可能使用宏来降低赋予权限被拒绝的可能。

文件作用
global_macros 和 te_macrosAndroid 提供的最常用的宏
users定义了Android中唯一的user(user u roles { r } level s0 range s0 - mls_systemhigh;)
roles定义了Android中唯二的role(role r;和role object_r;)
security_classes定义了Object的class
access_vectors定义了class的permissions
file_contexts定义了 Object的Context
genfs_contexts定义了虚拟文件(例如 proc 或 vfat)的Context
property_contexts定义了系统属性的Context,在设备启动时init 会读取此配置
service_contexts定义系统服务的Context,在设备启动时servicemanager 会读取此配置
seapp_contexts定义了应用和 /data/data 目录的Context,每次应用启动时zygote都会读取此配置;在设备启动时installd会读取此配置
mac_permissions.xml用于根据应用签名和包名分配 seinfo 标记,seinfo 用于在seapp_contexts为应用分配Context,在设备启动时system_server 会读取此配置

三、SEAndroid命令

SEAndroid不支持SELinux的Boolean模式,同时也没有移植全部的SELinux命令。

命令作用
getenforce获取SELinux状态模式Enforcing、Permissive和Disabled)
setenforce直到关机前临时改变SELinux状态,1是Enforcing 、0是Permissive
ls -Z查看文件的Context
ps -Z查看进程的Context
chcon修改资源的Context
restorecon将Context恢复默认值
dmesg | grep avc:查看本次启动中的系统拒绝日志
cat /proc/last_kmsg | grep avc:查看上一次启动系统的拒绝日志

四、规则编写

1.位置

Android不建议直接修改AOSP源码中system/sepolicy目录下的文件,这些是Android的核心安全策略,而建议在/device/manufacturer/device-name/sepolicy目录下添加设备专用的策略文件。在Android8.0及以上的版本Android将SELinux策略分成了四个部分:

策略说明
system/sepolicy/privateAndroid核心策略的实现细节(厂商无需关注)
system/sepolicy/publicAndroid核心策略公开的API
system/sepolicy/vendor提供给硬件制造商使用的策略(厂商可以不关注)
/device/manufacturer/device-name/sepolicyAndroid设备制造商对设备添加的策略

(system/sepolicy的private和public有点类似于java语言某个类定义的private变量,public变量和public函数。)
Android明确要求不允许删除AOSP中已存在的安全策略,且厂商应该为每个新增的进程编写策略。

2.编写方法

在Android4.4以下需要在/device/manufacturer/device-name/BoardConfig.mk中修改BOARD_SEPOLICY变量引用新的策略文件,在Android5.0以上会自动包含/device/manufacturer/device-name/sepolicy 下修改或添加策略文件和Context描述文件。
对于我们新增的进程,需要编写对应的.te文件

# test.te
# test是一个subject
type test, domain;

# 启动test的可执行文件
type test_exec, exec_type, file_type;

# 由init启动的服务进程需要使用这个宏来做转换
init_daemon_domain(test)

allow test file_type:class perm
allow test file_type:class perm
allow test file_type:class perm

在file_contexts中添加启动test的可执行文件

/system/bin/test u:object_r:test_exec:s0

3.设置标签

在SEAndroid中,为目录设置安全标签的方式主要有三种:预置在ROM中、挂载时设置和应用安装时设置。对于已经在ROM中创建好的目录可以将安全标签也预置在ROM中,即通过file_contexts直接指定目录设置标签;对于一些需要动态挂载的目录,如虚拟文件系统则需要根据genfs_contexts文件中的安全策略动态设置安全标签;由于Android的应用分为系统应用和第三方应用,因此需要在应用安装时根据应用签名为应用目录设置不同的安全标签,installd进程在创建应用数据目录的同时会设置它的安全标签。在已有安全标签的目录下创建的文件和目录会自动继承父目录的安全标签。

参考资料

https://source.android.google.cn/docs/security/features/selinux?hl=zh-cn
https://source.android.google.cn/docs/security/best-practices/system?hl=zh-cn#selinux
https://events.static.linuxfound.org/sites/events/files/slides/abs2014_seforandroid_smalley.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值