SELinux 专题

1.任务引出

一个用户自己的进程,可以访问用户自己的任何文件,这按照传统的unix/linux文件访问控制设定,是没问题的。但是如果一个firefox进程访问用户的ssh私钥(~/.ssh/id_rsa),这种行为总感觉怪怪的。

SELinux就是用来阻止这种不恰当行为的,此为MAC(Mandatory Access Control,强制访问控制模型)。前者叫DAC(Discretionary Access Control,自主访问控制模型)。和SELinux类似的还有一个叫AppArmor,同样基于LSM(Linux security module),被CentOS等发行版使用。

2.SELinux的介绍

SELinux(Security-Enhanced Linux)是一种安全性增强的Linux操作系统安全模块,它提供了一种基于强制访问控制(MAC)的安全机制来保护系统资源的安全。与传统的自由访问控制(DAC)不同,SELinux采用了更严格的安全策略,可以控制进程的访问行为,以及进程对文件、网络、进程等资源的访问权限。

SELinux最初由美国国家安全局(NSA)开发,目的是为了增强Linux的安全性能,防止恶意代码的攻击和利用漏洞,特别是在联网环境下。SELinux的安全性建立在强制访问控制机制上,它将资源和进程分为不同的安全级别,并对它们的交互进行限制和监控,从而实现对系统的高度保护。

SELinux采用了策略文件来定义系统的安全策略,管理员可以通过修改策略文件来控制进程、用户、文件等资源的访问权限。SELinux还提供了一系列的工具和命令,使管理员可以方便地管理和配置SELinux,包括设置安全标签、审计日志、故障排除等。

虽然SELinux的配置和管理相对复杂,但它在保护系统安全方面有着非常重要的作用,是一种重要的安全机制。许多Linux发行版都已经默认启用了SELinux,并将其作为操作系统的一部分进行维护。

3.SELinux的安装方式

Ubuntu系统默认情况下并没有集成SELinux。相反,Ubuntu采用了AppArmor作为默认的强制访问控制(MAC)安全机制,它提供了类似于SELinux的访问控制机制,但是与SELinux不同的是,它采用了更灵活的应用程序级别的安全策略,可以更好地适应桌面和服务器环境的需求。

不过,用户可以选择手动安装和配置SELinux来加强Ubuntu系统的安全性能。Ubuntu官方仓库中包含了SELinux的相关软件包,用户可以使用命令行工具来安装和配置SELinux,例如selinux-policy-defaultpolicycoreutilsauditd等。同时,Ubuntu社区也提供了一些文档和指南,以帮助用户了解和配置SELinux在Ubuntu上的使用。下面我们将展示如何在Ubuntu上安装并且配置SELinux:

1.确认系统版本和架构:SELinux支持在多种操作系统和架构上运行,但需要根据不同的版本和架构下载和安装相应的软件包。在Ubuntu上,可以使用uname -a命令来查看系统版本和架构信息。

(base) ljy@ubuntu:~$ uname -a 
Linux ubuntu 5.15.0-67-generic #74~20.04.1-Ubuntu SMP Wed Feb 22 14:52:34 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

接着移除Ubuntu系统内核中的Apparmor:

image-20230324190824608

2.安装SELinux软件包:Ubuntu官方仓库中包含了SELinux的相关软件包,可以使用apt-getaptitude命令来安装,例如:

systemctl stop apparmor
apt purge apparmor
apt update && sudo apt upgrade -yuf
apt install policycoreutils selinux-utils selinux-basics

上述的指令将会安装好SELinux的基本组件、策略规则、管理工具等。

3.配置SELinux:安装完成后,需要进行SELinux的基本配置,包括启用SELinux、设置策略规则、标签等。接着初次启动配置:

sudo selinux-activate

image-20230324194320191

此时则说明安装成功,不过不要着急进行重启,先补充一些关于SELinux模式的知识:

SELinux有着多种模式,

  • enforcing:强制模式,表示SELinux运行中,且正在限制domain/type
  • permissive:宽容模式,表示SELinux运行中,但仅有警告信息并未限制domain/type,多用于debug
  • disabled:关闭

我们此时输入指令来确定当前的姿态:

getenforce

此时显示为Disabled

这意味着SELinux已经准备就绪,处于激活的状态但是并没有打开。我们还可以输入一个指令来看看更多的信息:

sestatus

此时的结果是:

SELinux status:		disabled

接着重新启动Ubuntu,SELinux将会给系统资源加上标签,这个过程将会花费一段时间。

image-20230324194920955

接下来输入:

cat /etc/selinux/config

内容如下:

image-20230324204912141

接下来继续配置SELinux:

首先打开/etc/selinux/config

sudo nano /etc/selinux/config

激活SELinux,修改对应的行:

SELINUX=enforcing

保存退出并且重启,完成配置。

4.SELinux的配置方式

虽然前文我们讲述了如何在Ubuntu上配置相应的SELinux,但由于修改了对应的内核导致Ubuntu有较大的可能性重启后无法进入系统,为了稳定性和演示效果,我们最后还是选用了CentOS来进行相应的演示:

image-20230324214649282

CentOS默认集成了SELinux,并且状态为enabled。

接下来为了引入任务,我们还要介绍几个术语:

主体:在SELinux中,主体通常指的是进程。

客体:客体通常是用于信息共享、存储和通讯的系统资源(如文件、目录、套接字、共享内存等)。一个客体类别代表某个确定类型(如文件或套接字)的所有资源.一个客体类别的实例(如某个特定的文件或套接字)被称为一个客体, 如/etc/passwd 这个文件,我们称之为客体。

因此我们的任务就可以认为,一个叫”firefox“的进程作为主体,我们希望对客体,即(~/.ssh/id_rsa)文件作出一定的安全策略设置,限制主体对于客体的访问。

在 SELinux 当中,主体对客体所采用的访问类型为MAC,即强制访问控制。MAC 用于将系统中的信息分密级和类进行管理,以保证每个用户只能访问到那些被标明可以由他访问的信息的一种访问约束机制。通俗的来说,在强制访问控制下,用户(或其他主体)与文件(或其他客体)都被标记了固定的安全属性(如安全级、访问权限等),在每次访问发生时,系统检测安全属性以便确定一个用户是否有权访问该文件。

接下来还有一个非常重要的概念:

安全上下文:SELinux 系统中的进程和文件都标记了 SELinux 的上下文,这个上下文包含了许多有用的信息,包括SELinux用户(不同于Linux系统的用户)、角色(Role)、类型(Type)和级别(Security Level)等等。在运行 SELinux 的时候,这些上下文信息被用来辅助进行访问控制,它们可以看做是 SELinux 策略的“维度”。最新的 SELinux 综合提供了 RBAC、TE(类型增强)和 MLS(Multi-Security Level,多级别安全)三种访问控制机制。安全上下文通常的表示方式是: USER:ROLE:TYPE

AV/AVC:访问向量(Access vectors,Avs),用来表示策略的规则。如允许域访问各种系统客体,一个 AV 是一套许可。一个基本的 AV 规则是主体和客体的类型对,AV 规则的语法如下:

<av_kind><source_type(s)><target_type(s)>:<class(es)>
<permission(s)>

PS:由于历史原因,一个进程的类型通常被称为一个域(域类型)。“域”和“域类型”都是指同一个,在平时我们看到文档中以及日常交流中,我们认为域、域类型、主体类型和进程类型都是指同一种意思。

因为 SELinux 默认不允许任何访问,所以,所有的访问都必须明确授权,不管用户/组ID是什么, 在SELinux中,通过allow语句对主体授权对客体的访问权限。Allow规则由四部分组成:源类型(Source type(s))是尝试访问进程的域类型;目标类型(Target type(s))被进程访问的客体的类型;客体类别(Object class(es))是指定允许访问的客体的类型,如 file,dir,socket 等;许可(Pemission(s))象征目标类型允许源类型访问客体类型的访问种类。下面举个例子:

allow user_t bin_t:file {read execute getattr}

上述例子显示了TE allow规则的基础语法,这个规则包含两个类型标识符:源类型(或主体类型或域)user_t,目标类型(或客体类型)bin_t,标识符 file 是定义在策略的客体类别名称,表示的是一个普通文件,大括号的许可是文件客体类别有效许可。整条规则解释是:拥有域类型user_t的进程可以读/执行或获取具体有bin_t类型的文件客体的属性。

5.SELinux的使用demo:

我们将以SELinux在Httpd中的运用为例子,展示具体的使用方式:

首先安装并且启动Httpd服务(httpd也就是apache):

[centos@centos ~]$ sudo yum install httpd
[centos@centos ~]$ service httpd start

此时我们访问127.0.0.1是这样的:

image-20230326101750517

此时我们的Web服务器目录下还没有文件,显示了默认的页面。验证如下:

[centos@centos ~]$ ll /var/www/html
total 0

接着我们在home下面新建一个文件index.html,并且移动到/var/www/html文件路径下面。

[centos@centos ~]$ vi index.html

hello,world

[centos@centos ~]$ sudo mv index.html /var/www/html/
[centos@centos ~]$ cd /var/www/html/
[centos@centos html]$ ls
index.html

接下来我们再次访问对应的网页:

image-20230326102025543

此时无法访问,并且SELinux也会弹出安全性警报,由此可以推断出SELinux阻止了firefox访问我们新建的那个index.html

我们可以查看/var/log/audit文件夹下面的audit.log文件查看原因(要使用root访问)

image-20230326102905314

猜测应该是SELinux限制了httpd对index.html的read操作。

接下来我们查看一下index.html安全上下文信息:

[ljy@localhost ~]$ ls -Z /var/www/html
-rw-r--r--. root root unconfined_u:object_r:home_root_t:s0 index.html

由此可见index.html的type是home_root_t,查看/var/www/html的目录的安全上下文的结果如下:

[ljy@localhost ~]$ ls -Z -d /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html

我们前面已经查询过,当前SELinux的状态为enforcing,所以对于undefined的行为是禁止的。为了解决这个问题,我们准备手动改变index.html的安全上下文来解决问题。

此处我们选择使用chcon来改变文件的上下文信息:

image-20230326104123325

选择一个参考性的文件,用来作为对index.html安全上下文修改的具体模板。做法是在/var/www/html目录下新建一个model.html,然后根据这个新建文件来修改目标的安全上下文:

[root@localhost ljy]# chcon -t httpd_sys_content_t /var/www/html/index.html
[root@localhost ljy]# ls -Z -d /var/www/html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html
[root@localhost ljy]# sudo vi /var/www/html/model.html
[root@localhost ljy]# ls -Z /var/www/html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 model.html
[root@localhost ljy]# sudo chcon --reference=/var/www/html/model.html /var/www/html/index.html
[root@localhost ljy]# ls -Z /var/www/html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 model.html

修改上下文后再次访问网站就成功了:

image-20230326104642438