跳至内容

SELinux 安全

随着内核版本 2.6 的出现,引入了一个新的安全系统,用于提供支持访问控制安全策略的安全机制。

该系统称为 SELinux (Security Enhanced Linux),由 NSA (National Security Agency) 创建,用于在 Linux 内核子系统中实现强大的 Mandatory Access Control (MAC) 架构。

如果在你的职业生涯中,你曾经禁用或忽略过 SELinux,那么本文档将是你了解该系统的一个良好开端。SELinux 旨在限制特权或消除因程序或守护进程泄露而带来的风险。

在开始之前,你应该知道 SELinux 主要用于 RHEL 发行版,尽管也可以将其实现到其他发行版,如 Debian(但祝你好运!)。Debian 系列的发行版通常集成了 AppArmor 系统,其工作方式与 SELinux 不同。

概述

SELinux (Security Enhanced Linux) 是一个强制访问控制系统。

在 MAC 系统出现之前,标准的访问管理安全是基于 DAC (Discretionary Access Control) 系统的。应用程序或守护进程以 UIDSUID (Set Owner User Id) 权限运行,这使得可以根据该用户评估权限(对文件、套接字和其他进程…)。这种操作不足以限制损坏程序的权限,可能允许其访问操作系统子系统。

MAC 系统加强了保密性和完整性信息的隔离,以实现一个遏制系统。遏制系统独立于传统的权限系统,没有超级用户的概念。

每次系统调用时,内核会查询 SELinux 以确定是否允许执行该操作。

SELinux

SELinux 使用一组规则(策略)来实现这一点。提供了两组标准规则(targetedstrict),每个应用程序通常提供自己的规则。

SELinux 上下文

SELinux 的操作与传统的 Unix 权限完全不同。

SELinux 安全上下文由 身份 + 角色 + 的三元组定义。

用户的身份直接取决于其 Linux 帐户。一个身份被分配一个或多个角色,但每个角色对应一个域,并且只有一个。

用户对资源的权限是根据安全上下文的域(以及因此的角色)来评估的。

SELinux context

“域”和“类型”这两个术语是相似的。通常,“域”指代进程,“类型”指代对象。

命名约定是:user_u:role_r:type_t

安全上下文在用户登录时根据其角色分配。文件的安全上下文由 chcon (change context) 命令定义,我们将在本文档后面介绍。

考虑 SELinux 的以下组成部分

  • 主体
  • 客体
  • 策略
  • 模式

当一个主体(例如应用程序)尝试访问一个客体(例如文件)时,Linux 内核的 SELinux 部分会查询其策略数据库。根据运行模式,SELinux 在成功时授权访问客体,否则会将失败记录在 /var/log/messages 文件中。

标准进程的 SELinux 上下文

进程的权限取决于其安全上下文。

默认情况下,进程的安全上下文由启动它的用户(身份 + 角色 + 域)的上下文定义。

域是一个特定的类型(在 SELinux 意义上),与进程相关联,并(通常)从启动它的用户继承。其权限以对与客体关联的类型的授权或拒绝来表示。

安全域为 D 的进程可以访问类型为 T 的客体。

The SELinux context of standard processes

重要进程的 SELinux 上下文

大多数重要程序都被分配了一个专用的域。

每个可执行文件都标记有一个专用的类型(此处为 sshd_exec_t),它会自动将关联的进程切换到 sshd_t 上下文(而不是 user_t)。

这种机制至关重要,因为它尽可能地限制了进程的权限。

The SELinux context of an important process - example of sshd

管理

semanage 命令管理 SELinux 规则。

semanage [object_type] [options]

示例

semanage boolean -l
选项 注意事项
-a 添加对象
-d 删除对象
-m 修改对象
-l 列出对象

在 Rocky Linux 上,semanage 命令可能默认未安装。

在不知道提供该命令的包的情况下,你应该使用以下命令搜索其名称

dnf provides */semanage

然后安装它

sudo dnf install policycoreutils-python-utils

管理布尔对象

布尔值允许进程的遏制。

semanage boolean [options]

列出可用的布尔值

semanage boolean –l
SELinux boolean    State Default  Description
…
httpd_can_sendmail (off , off)  Allow httpd to send mail
…

注意

如你所见,有一个 default 状态(例如,启动时)和一个运行状态。

setsebool 命令用于更改布尔对象的状态

setsebool [-PV] boolean on|off

示例

sudo setsebool -P httpd_can_sendmail on
选项 注意事项
-P 更改启动时的默认值(否则仅在重启前有效)
-V 删除对象

警告

别忘了使用 -P 选项以使状态在下次启动后仍然有效。

管理端口对象

semanage 命令用于管理端口类型的对象

semanage port [options]

示例:允许 httpd 域进程使用端口 81

sudo semanage port -a -t http_port_t -p tcp 81

运行模式

SELinux 有三种运行模式

  • Enforcing (强制)

Rocky Linux 的默认模式。访问将根据当前规则受到限制。

  • Permissive (允许)

规则会被检查,访问错误会被记录,但访问不会被阻止。

  • Disabled (禁用)

什么都不会受到限制,什么都不会被记录。

默认情况下,大多数操作系统都配置为 SELinux 处于 Enforcing 模式。

getenforce 命令返回当前运行模式

getenforce

示例

$ getenforce
Enforcing

sestatus 命令返回有关 SELinux 的信息

sestatus

示例

$ sestatus
SELinux status:       enabled
SELinuxfs mount:     /sys/fs/selinux
SELinux root directory:    /etc/selinux
Loaded policy name:        targeted
Current mode:             enforcing
Mode from config file:     enforcing
...
Max kernel policy version: 33

setenforce 命令更改当前运行模式

setenforce 0|1

将 SELinux 切换到 permissive 模式

sudo setenforce 0

/etc/sysconfig/selinux 文件

/etc/sysconfig/selinux 文件允许你更改 SELinux 的运行模式。

警告

禁用 SELinux 的风险自负!最好学习 SELinux 的工作原理,而不是系统性地禁用它!

编辑 /etc/sysconfig/selinux 文件

SELINUX=disabled

注意

/etc/sysconfig/selinux 是指向 /etc/selinux/config 的符号链接

重新启动系统

sudo reboot

警告

注意 SELinux 模式更改!

在禁用模式下,新创建的文件将没有任何标签。

要重新激活 SELinux,你将不得不重新定位整个系统的标签。

为整个系统打标签

sudo touch /.autorelabel
sudo reboot

策略类型

SELinux 提供两种标准规则类型

  • Targeted (目标):仅保护网络守护进程(dhcpd, httpd, named, nscd, ntpd, portmap, snmpd, squidsyslogd
  • Strict (严格):保护所有守护进程

上下文

安全上下文的显示使用 -Z 选项。它与许多命令相关联

示例

id -Z # the user's context
ls -Z # those of the current files
ps -eZ # those of the processes
netstat –Z # for network connections
lsof -Z # for open files

matchpathcon 命令返回目录的上下文。

matchpathcon directory

示例

sudo matchpathcon /root
 /root system_u:object_r:admin_home_t:s0

sudo matchpathcon /
 /      system_u:object_r:root_t:s0

chcon 命令修改安全上下文

chcon [-vR] [-u USER] [–r ROLE] [-t TYPE] file

示例

sudo chcon -vR -t httpd_sys_content_t /data/websites/
选项 注意事项
-v 切换到详细模式
-R 递归应用
-u,-r,-t 应用于用户、角色或类型

restorecon 命令恢复默认安全上下文(由规则提供的)

restorecon [-vR] directory

示例

sudo restorecon -vR /home/
选项 注意事项
-v 切换到详细模式
-R 递归应用

要使上下文更改能够通过 restorecon 持续存在,你必须使用 semanage fcontext 命令修改默认文件上下文

semanage fcontext -a options file

注意

如果你正在为一个非标准的系统文件夹进行上下文切换,创建规则然后应用上下文是一个好习惯,如下面的示例!

示例

sudo semanage fcontext -a -t httpd_sys_content_t "/data/websites(/.*)?"
sudo restorecon -vR /data/websites/

audit2why 命令

audit2why 命令指示 SELinux 拒绝的原因

audit2why [-vw]

获取 SELinux 最近一次拒绝原因的示例

sudo cat /var/log/audit/audit.log | grep AVC | grep denied | tail -1 | audit2why
选项 注意事项
-v 切换到详细模式
-w 翻译 SELinux 拒绝的原因,并提出解决方案(默认选项)

深入了解 SELinux

audit2allow 命令根据“audit”文件中的一行创建一个模块,以允许 SELinux 操作(当不存在模块时)

audit2allow [-mM]

示例

sudo cat /var/log/audit/audit.log | grep AVC | grep denied | tail -1 | audit2allow -M mylocalmodule
选项 注意事项
-m 仅创建模块(*.te
-M 创建模块、编译并打包(*.pp

配置示例

执行命令后,系统会返回命令提示符,但预期的结果并未显示:屏幕上没有错误消息。

  • 步骤 1:读取日志文件,知道我们感兴趣的消息是 AVC (SELinux) 类型,拒绝 (denied),并且是最新的(因此是最后一条)。
sudo cat /var/log/audit/audit.log | grep AVC | grep denied | tail -1

消息被正确隔离,但对我们没有帮助。

  • 步骤 2:使用 audit2why 命令读取隔离的消息,以获得更明确的消息,其中可能包含解决我们问题的方案(通常是需要设置的布尔值)。
sudo cat /var/log/audit/audit.log | grep AVC | grep denied | tail -1 | audit2why

有两种情况:要么我们可以放置一个上下文或填充一个布尔值,要么我们必须转到第 3 步来创建我们自己的上下文。

  • 步骤 3:创建你自己的模块。
$ sudo cat /var/log/audit/audit.log | grep AVC | grep denied | tail -1 | audit2allow -M mylocalmodule
Generating type enforcement: mylocalmodule.te
Compiling policy: checkmodule -M -m -o mylocalmodule.mod mylocalmodule.te
Building package: semodule_package -o mylocalmodule.pp -m mylocalmodule.mod

$ sudo semodule -i mylocalmodule.pp

作者:Antoine Le Morvan

贡献者:Steven Spencer, markooff, Ganna Zhyrnova