1.Selinux简介
selinux全称(Security-Enhanced Linux)安全增强型Linux,它是一个Linux内核模块,也是Linux的一个安全子系统。
2.Selinux的作用及权限管理机制
2.1 Selinux的作用
SELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。
2.2 DAC
在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:某个资源是否拥有对应用户的权限(读、写、执行)。
只要访问这个资源的进程符合以上的条件就可以被访问。
而最致命问题是,root 用户不受任何管制,系统上任何资源都可以无限制地访问。
这种权限管理机制的主体是用户,也称为自主访问控制(DAC)。
2.3 MAC
在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。
这样一来,即使进程是以 root 身份运行的,也需要判断这个进程的类型以及允许访问的资源类型才能决定是否允许访问某个资源。进程的活动空间也可以被压缩到最小。
即使是以 root 身份运行的服务进程,一般也只能访问到它所需要的资源。即使程序出了漏洞,影响范围也只有在其允许访问的资源范围内。安全性大大增加。
这种权限管理机制的主体是进程,也称为强制访问控制(MAC)。
而 MAC 又细分为了两种方式,一种叫类别安全(MCS)模式,另一种叫多级安全(MLS)模式。
2.4 DAC和MAC对比
在DAC模式下,只要相应的目录有相应的用户的权限,就可以被访问,而在MAC模式下,好要受进程允许访问目录范围的限制
3.SELinux基本概念
3.1 主体(Subject)
可以完全等同于进程
3.2 对象(Object)
被主体访问的资源。可以是文件、目录、端口、设备等。
3.3 政策和规则(Policy & Rule)
系统中通常有大量的文件和进程,为了节省时间和开销,通常我们只是选择性地对某些进程进行管制。
而哪些进程需要管制、要怎么管制是由政策决定的。
一套政策里面有多个规则。部分规则可以按照需求启用或禁用(以下把该类型的规则称为布尔型规则)。
规则是模块化、可扩展的。在安装新的应用程序时,应用程序可通过添加新的模块来添加规则。用户也可以手动地增减规则。
3.4 安全上下文(Security Context)
安全上下文是 SELinux 的核心,在selinux中,** 访问控制属性叫做安全上下文。 **所有对象(文件、进程间通信通道、套接字、网络主机等)和主体(进程)都有一个与之关联的安全上下文。
安全上下文一般分为[进程安全上下文]和[文件安全上下文]
一个进程上下文一般对应多个文件安全上下文
只有两者的安全上下文对应上了,进程才能访问文件。它们的对应关系由政策中的规则决定。
一个安全上下文包含三个元素:
用户(user)、角色(role)和类型标识符(type identifiers)
对进程来说:分别表示用户、角色、类型标识符也被称为域
对客体来说:前两项基本没有实际用途,role通常为object_r,user通常位创建这个对象的进程的user,对访问控制没有影响
需要注意的是,单纯的移动文件操作并不会改变文件的安全上下文。
安全上下文的结构及含义:
安全上下文有四个字段,分别用冒号隔开。形如:system_u:object_r:admin_home_t:s0。
用户(user) | 角色(Role) | 类型(Type) | 级别(Level) | |
---|---|---|---|---|
进程安全上下文 | 主要分为两类 system_u为系统服务进程,受到管制unconfined_u为不管制进程,通常都是用户自己开启,如bash | 主要分两类 system_r为系统服务进程,受到管制 unconfined_r为不管制进程,通常都是用户自己开启的,如bash | 在targeted模式下唯一需要关注的字段 在targeted模式下只有两者的类型对应上了(不代表相同),进程才能访问文件 | MLC安全级别。仅在MLS模式下才有意义 |
文件安全上下文 | 主要分为两类 system_u为系统服务创建的文件 unconfined_u为用户自己创建的文件 | 均为object_r表示一个文件 | 在targeted模式下唯一需要关注的字段。 在targeted模式下只有两者的类型对应上了(不代表相同),进程才能访问文件 | MLC安全级别。仅在MLS模式下才有意义 |
3.5 Selinux的工作模式
SELinux 有三种工作模式,分别是:
- enforcing:强制模式。违反 SELinux 规则的行为将被拦截并记录到日志中,执行会有问题。
- permissive:宽容模式。违反 SELinux 规则的行为会记录到日志中,但是拒绝请求,执行不会有问题。一般为调试用。
- disabled:关闭 SELinux。
SELinux 工作模式可以在 /etc/selinux/config 中设定。
如果想从 disabled 切换到 enforcing 或者 permissive 的话,需要重启系统。反过来也一样。
enforcing 和 permissive 模式可以通过 setenforce 1|0 命令快速切换。
当前系统的selinux模式可以通过getenforce来获取。
SELinux 日志的记录需要借助 auditd.service 这个服务,请不要禁用它。
宽容模式的日志一般以permissive=1结尾,强制模式会以permissive=0结尾:
// 宽容模式
avc: denied { accept } for pid=1430 comm="abc" lport=40777 scontext=u:r:abcservice:s0 tcontext=u:r:abcservice:s0 tclass=tcp_socket permissive=1
// 强制模式
avc: denied { accept } for pid=1430 comm="abc" lport=40777 scontext=u:r:abcservice:s0 tcontext=u:r:abcservice:s0 tclass=tcp_socket permissive=0
3.6 Selinux的工作流程
3.6.1 显示安全上下文
在命令中加上Z可以显示主体、课体的上下文
● ls -Z能显示文件系统的安全上下文
● ps -Z能才是进程的安全上下文
● id -Z能显示shell的安全上下文:joe:usr_t:usr_t
3.6.2 TE的访问控制
在SELinux中,默认时没有允许规则的,也没有超级用户。被允许的访问必须由规则给出。
一条规则如下:
allow Source type(s) Target type(s): Object class(es) Permission(s)
比如这样的访问规则:
allow user_t bin_t : file {read execute getattr};
表示允许域为user_t的进程对type为bin_t的文件具有读、执行、得到属性的操作
4.Selinux基本操作
4.1 查询文件或目录的安全上下文
命令基本用法:
ls -Z
比如查询/etc/hosts的安全上下文:
ls -Z /etc/hosts
执行结果:
-rw-r--r--. root root system_u:object_r:net_conf_t:s0 /etc/hosts
/etc/hosts的安全上下文标签是net_conf_t
4.2 avc log 分析
继android KK 4.4 版本后,Google 默认启用了SELinux, 并会把SELinux 审查异常打印在kernel log 或者 android log(L 版本)中,对应的关键字是: “avc: denied” 或者"avc: denied"。
一个Selinux拒绝条目的示例:
type=AVC msg=audit(1623753215.015:708): avc: denied { open } for pid=1401 comm="httpd" path="/var/www/html/test.html" dev="vda1"
ino=42188726 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:tmp_t:s0 tclass=fil
以上日志可以解读成: “pid 为 1401 的 httpd 进程试图打开托管在 vda1 设备上的 /var/www/html/test.html 文件; 该文件的 inode 号是42188726,并有分配给它的安全上下文标签 system_u:system_r:httpd_t:s0 而该文件本身的上下文是 unconfined_u:object_r:tmp_t:s0”
type=AVC
表示日志类型, AVC 是 Access Vector Cache 访问向量缓存的缩写; 缓存表示的意思是: 因为 SELinux 有太多的东西要报告,所以日志可能不会显示所有的东西,就放在"缓存"里; AVC 条目日志只会在 audit.log 文件中出现
audit( 1623753215.015 )
时间戳,表示从 1970年1月1日 到现在的秒数; 可以使用 date -d @ 1623753215.015 进行转换
avc
表示日志类型
denied
表示 SELinux 做了什么, 拒绝或是允许; 如果 SELinux 处于 permissive mode,那么即使是允许了,但依旧会被记录为拒绝
{ open }
请求执行的权限,该示例为"打开"权限,还可以是 read 和 write
for pid=1401
哪一个进程号尝试执行上一行的打开操作
comm=“httpd”
进程的命令,限制在15个字符以内,有助于用户在进程消失的情况下确定进程(因为 PID 只有进程还在运行的时候才有效)
path(也可能是 name)
被访问的目标名称,这个字段取决于目标本身; 可以是 path= 也可以是 capacity= 还可以是 src= 等等…
dev=vda1
表示目标所在的设备或文件系统
ino=42188726
目标的 inode number, 可以使用 find / -inum 42188726 查找到目标文件
scontext
Target context; 当前文件的上下文
tcontext
Target context; 当前文件的上下文
tclass=file
目标的类型,还有可能是其他类型,如: dir
4.3 avc log 抓取和策略添加
4.3.1 抓取日志
avc log会写在内核日志中,所以只要获取到dmesg的日志就可以找到avc log了,比如:
logcat | grep avc
或者
dmesg | grep avc
将log写入文本
dmesg | grep avc >d:\kernel.txt
4.3.2 策略添加
比如avc报了以下log:
avc: denied { create } for name="hsdi_tmp" scontext=u:r:system_app:s0 tcontext=u:object_r:protect_f_data_file:s0 tclass=dir permissive=0
那么就可以通过在system_app.te文件中加入一下语句来消除相关权限问题:
allow system_app protect_f_data_file:dir create;