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) 系统的。应用程序或守护进程以 UID 或 SUID (Set Owner User Id) 权限运行,这使得可以根据该用户评估权限(对文件、套接字和其他进程…)。这种操作不足以限制损坏程序的权限,可能允许其访问操作系统子系统。
MAC 系统加强了保密性和完整性信息的隔离,以实现一个遏制系统。遏制系统独立于传统的权限系统,没有超级用户的概念。
每次系统调用时,内核会查询 SELinux 以确定是否允许执行该操作。
SELinux 使用一组规则(策略)来实现这一点。提供了两组标准规则(targeted 和 strict),每个应用程序通常提供自己的规则。
SELinux 上下文¶
SELinux 的操作与传统的 Unix 权限完全不同。
SELinux 安全上下文由 身份 + 角色 + 域 的三元组定义。
用户的身份直接取决于其 Linux 帐户。一个身份被分配一个或多个角色,但每个角色对应一个域,并且只有一个。
用户对资源的权限是根据安全上下文的域(以及因此的角色)来评估的。
“域”和“类型”这两个术语是相似的。通常,“域”指代进程,“类型”指代对象。
命名约定是:user_u:role_r:type_t。
安全上下文在用户登录时根据其角色分配。文件的安全上下文由 chcon
(change context) 命令定义,我们将在本文档后面介绍。
考虑 SELinux 的以下组成部分
- 主体
- 客体
- 策略
- 模式
当一个主体(例如应用程序)尝试访问一个客体(例如文件)时,Linux 内核的 SELinux 部分会查询其策略数据库。根据运行模式,SELinux 在成功时授权访问客体,否则会将失败记录在 /var/log/messages
文件中。
标准进程的 SELinux 上下文¶
进程的权限取决于其安全上下文。
默认情况下,进程的安全上下文由启动它的用户(身份 + 角色 + 域)的上下文定义。
域是一个特定的类型(在 SELinux 意义上),与进程相关联,并(通常)从启动它的用户继承。其权限以对与客体关联的类型的授权或拒绝来表示。
安全域为 D 的进程可以访问类型为 T 的客体。
重要进程的 SELinux 上下文¶
大多数重要程序都被分配了一个专用的域。
每个可执行文件都标记有一个专用的类型(此处为 sshd_exec_t),它会自动将关联的进程切换到 sshd_t 上下文(而不是 user_t)。
这种机制至关重要,因为它尽可能地限制了进程的权限。
管理¶
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
,squid
和syslogd
) - 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