本章目标:
- 介绍SELinux如何保护资源以及如何选择执行模式
- 配置文件的SELinux上下文,以控制进程如何与该文件进行交互
- 配置SELinux布尔值,从而允许针对不同的访问需求更改运行时策略
- 调查SELinux日志消息并对SELinux AVC拒绝问题进行故障排除
文章目录
一、更改SELinux到强制模式
1. SELinux如何保护资源
SELinux在Linux中具有重要的安全用途,它可以允许或拒绝访问文件及其他资源,且精准度相比用户权限要大幅提高。
文件权限控制了哪些用户或用户组可以访问哪些特定文件。但是,被授予对特定文件的读取或写入权限的用户可以按用户选择的任何方式使用该文件,即便这种使用方式并不是文件本该采用的方式。
例如,对于文件的写入权限而言,结构化数据文件是否应当设计为只能使用特定的程序写入,但其他编辑器仍可以打开和修改此文件,而这可能会导致损坏?
文件权限并不能阻止此类不合要求的访问。它们未设计为控制如何使用文件,而仅仅是控制谁可以读取、写入或运行文件。
SELinux由应用开发人员定义的若干组策略组成,这些策略准确声明了对于应用使用的每个二进制可执行文件、配置文件和数据文件,哪些操作和访问权限是恰当且被允许的。这被称为目标政策,因为会编写一个策略以涵盖单个应用的活动。策略声明了各个程序、文件和网络端口上放置的预定义标签。
2. 为什么使用SECURITY ENHANCED LINUX?
并非所有安全问题都可以提前预测。SELinux实施了一组可以防止一个应用程序的弱点影响其他应用或基础系统的访问规则。SELinux提供了一个额外的安全层,此外还增加了一层复杂结构,这令该子系统的新用户感到烦恼。学习使用SELinux可能会需要一些时间,但执行政策意味着系统某一部分的弱点不会扩散到其他部分。如果SELinux在特定的子系统上运行不佳,则可以关闭该特定服务的执行,直至找到潜在问题的解决方案。
SELinux有三种模式:
- 强制:SELinux强制执行访问控制规则。计算机通常在该模式下运行。
- 许可:SELinux处于活动状态,但并不强制执行访问控制规则,而是记录违反规则的警告。该模式主要用于测试和故障排除。
- 禁用:SELinux完全关闭 - 不拒绝任何SELinux违规,甚至不予记录。不建议禁用SELinux
3. SELinux安全的基本概念
Security Enhanced Linux(SELinux)是一个额外的系统安全层。SELinux的主要目标是防止已遭泄露的系统服务访问用户数据。大多数Linux管理员都熟悉标准的用户/组/其他权限安全模型。这种基于用户和组的模型称为自由决定的访问控制。SELinux提供另一层安全,它基于对象并由更加复杂的规则控制,称为强制访问控制。
要允许远程匿名访问Web服务器,必须打开防火墙端口。不过,这也让恶意人员有机会通过安全漏洞侵入系统。如果他们成功入侵了Web服务器进程,就可以获得进程的权限。具体来说,就是apache用户和apache组的权限。该用户和组对文档根目录 /var/www/html 具有读取权限。它还可以访问 /tmp 和 /var/tmp,以及全局可写的其他任何文件和目录。
SELinux是用于确定哪个进程可以访问哪些文件、目录和端口的一组安全规则。每个文件、进程、目录和端口都具有专门的安全标签,称为SELinux上下文。上下文是一个名称,SELinux策略使用它来确定某个进程能否访问文件、目录或端口。除非显式规则授予访问权限,否则,在默认情况下,策略不允许任何交互。如果没有允许规则,则不允许访问。
SELinux标签具有多种上下文:用户(user)、角色(role)、类型(type)和敏感度(sensitivity)。目标策略(即红帽企业Linux中启用的默认策略)会根据第三个上下文(即类型上下文)来制定自己的规则。类型上下文名称通常以 _t 结尾。
Web服务器的类型上下文是httpd_t。通常位于 /var/www/html 中的文件和目录的类型上下文是 httpd_sys_content_t 。通常位于**/tmp** 和 /var/tmp 中的文件和目录上下文是tmp_t。Web服务器端口的类型上下文是http_port_t。
Apache具有类型上下文httpd_t。有一个策略规则允许Apache访问具有httpd_sys_content_t类型上下文的文件和目录。默认目录下,在 /var/www/html 和其他Web服务器目录中找到的文件具有 httpd_sys_content_t 类型上下文。策略中没有允许规则适用于通常位于**/tmp** 和 /var/tmp 中的文件,因此不允许访问。在启用SELinux的情况下,破坏了Web服务器进程的恶意用户将无法访问 /tmp 目录。
MariaDB服务器具有类型上下文mysqld_t。默认情况下,在 /data/mysql 中找到的文件具有mysqld_db_t类型上下文。该类型上下文允许MariaDB访问这些文件,但禁止其他服务(如Apache Web服务)访问。
许多处理文件的命令都使用 -Z 选项来显示或设置SELinux上下文。例如,ps、ls、cp和mkdir都使用 -Z 选项显示或设置SELinux上下文。
[root@host ~]# ps axZ
LABEL PID TTY STAT TIME COMMAND
system_u:system_r:init_t:s0 1 ? Ss 0:09 /usr/lib/systemd/...
system_u:system_r:kernel_t:s0 2 ? S 0:00 [kthreadd]
system_u:system_r:kernel_t:s0 3 ? S 0:00 [koftirqd/0]
...output omitted...
[root@host ~]# systemctl start httpd
[root@host ~]# ps -ZC httpd
LABEL PID TTY TIME CMD
system_u:system_r:httpd_t:s0 1608 ? 00:00:05 httpd
system_u:system_r:httpd_t:s0 1609 ? 00:00:00 httpd
...output omitted...
[root@host ~]# ls -Z /home
drwx------. root root system_u:object_r:lost_found_t:s0 lost+found
drwx------. student student unconfined_u:object_r:user_home_dir_t:s0 student
drwx------. visitor visitor unconfined_u:object_r:user_home_dir_t:s0 visitor
[root@host ~]# ls -Z /var/www
drwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 cgi-bin
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 error
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 icons
4. 更改当前的SELinux模式
SELinux子系统提供了显示和更改模式的工具。要确定当前的SELinux模式,需要运行getenforce命令。要将SELinux设置为其他模式,需要使用setenforce命令:
[user@host ~]# getenforce
Enforcing
[user@host ~]# setenforce
usage: setenforce [ Enforcing | Permissive | 1 | 0 ]
[user@host ~]# setenforce 0
[user@host ~]# getenforce
Permissive
[user@host ~]# setenforce Enforcing
[user@host ~]# getenforce
Enforcing
或者,我们可以在启动时通过将内核传递参数来设置SELinux模式:内核参数enforcing=0将以许可模式启动系统;值enforcing=1则设置强制模式。此外,我们还可以通过传递内核参数selinux=0来彻底禁用SELinux。值selinux=1将启用SELinux。
5. 设置默认SELinux模式
我们也可以使用 /etc/selinux/config 文件来持久配置SELinux。在以下示例中(默认配置),配置文件会将SELinux设置为enforcing。注释中还显示了其他有效值:permissive和disabled。
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes
# are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
系统在启动时会读取此文件并如文中所示配置SELinux。内核参数(selinux=0|1和enforcing=0|1)将覆盖此配置。
二、控制SELinux文件上下文
1. 初始SELinux上下文
在运行SELinux的系统上,所有进程和文件都会有相应的标签。标签代表了与安全有关的信息,称为SELinux上下文。
新文件通常从父目录继承其SELinux上下文,从而确保它们具有适当的上下文。
但是,有两种不同的方式可能会破坏该继承过程。首先,如果在与最终目标位置不同的位置创建文件,然后移动文件,则该文件将具有创建它时所在目录的SELinux上下文,而不是目标目录的SELinux上下文。其次,如果是复制一个保留SELinux上下文的文件(正如使用cp -a命令),则SELinux上下文将反映原始文件的位置。
以下示例演示了继承关系及存在的缺陷。以 /tmp 中创建的这两个文件为例,一个移动到 /var/www/html,另一个复制到同一目录中。必须注意文件的SELinux上下文。移动到 /var/www/html 目录的文件保留了 /tmp 目录的文件上下文。复制到 /var/www/html 目录中的文件则继承了 /var/www/html 目录的SELinux上下文。
ls -Z命令显示文件的SELinux上下文。注意文件的标签:
[root@host ~]# ls -Z /var/www/html/index.html
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
ls -Zd命令显示目录的SELinux上下文:
[root@host ~]# ls -Zd /var/www/html/
drwxr-xr-x. root root system_u:object_u:object_r:httpd_sys_content_t:s0 /var/www/html/
注意,/var/www/html/index.html 与父目录 /var/www/html/ 具有相同的标签。现在,在 /var/www/html 目录之外创建文件并注意它们的文件上下文:
[root@host ~]# touch /tmp/file1 /tmp/file2
[root@host ~]# ls -Z /tmp/file*
unconfined_u:object_r:user_tmp_t:s0 /tmp/file1
unconfined_u:object_r:user_tmp_t:s0 /tmp/file2
将其中一个文件移动到 /var/www/html 目录,复制另一个文件,同时注意每个文件的标签:
[root@host ~]# mv /tmp/file1 /var/www/html/
[root@host ~]# cp /tmp/file2 /var/www/html/
[root@host ~]# ls -Z /var/www/html/file*
unconfined_u:object_r:user_tmp_t:s0 /var/www/html/file1
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/file2
移动的文件保留了自己的原始标签,而复制的文件则继承了 /var/www/html 目录的标签。**unconfined_u:**代表用户,**object_r:**代表角色,s0代表级别。敏感度级别0为最低级别。
2. 更改文件的SELinux上下文
用于更改文件SELinux上下文的命令包括:semanage fcontext、restorecon和chcon。
为文件设置SELinux上下文的首先方法是使用semanage fcontext命令来声明文件的默认标签,然后使用restorecon命令将该上下文应用于文件。这样可确保标签符合预期,即便对文件系统完全更新标记之后也是如此。
chcon命令更改SELinux上下文。chcon设置存储在文件系统中的文件安全上下文。它对于测试和实验很有用。但是,它不会将上下文更改保存到SELinux上下文数据库中。当restorecon命令运行时,chcon命令所做的更改也同样无法保留。此外,如果对整个文件系统进行重新标记,则使用chcon更改过的文件的SELinux上下文将恢复。
以下屏幕显示正在创建的目录。该目录的类型值为default_t:
[root@host ~]# mkdir /virtual
[root@host ~]# ls -Zd /virtual
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /virtual
chcon命令更改 /virtual 目录的文件上下文:类型值更改为httpd_sys_content_t:
[root@host ~]# chcon -t httpd_sys_content_t /virtual
[root@host ~]# ls -Zd /virtual
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /virtual
运行restorecon命令,类型值恢复为default_t的值。注意Relabeled消息:
[root@host ~]# restorecon -v /virtual
Relabeled /virtual from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0
[root@host ~]# ls-Zd /virtual
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /virtual
3. 定义SELinux默认文件上下文规则
semanage fcontext命令可显示和修改restorecon用来设置默认文件上下文的规则。它使用扩展正则表达式来指定路径和文件名。fcontext规则中最常用的扩展正则表达式是 (/.*)?,表示“可选择匹配后跟任何数量字符的/”。它将会匹配在表达式前面列出的目录并递归地匹配该目录中的所有内容。
3.1. 基本文件上下文操作
下表可作为semanage fcontext选项的参考,用于添加、删除或列出SELinux文件上下文。
semanage fcontext命令
选项 | 描述 |
---|---|
-a,–add | 添加指定对象类型的记录 |
-d,–delete | 删除指定对象类型的记录 |
-l,–list | 列出指定对象类型的记录 |
为了确保我们拥有管理SELinux上下文的工具,根据需要安装policycoreutil软件包和policycoreutil-python软件包。这两个软件包中分别包含restorecon命令和semanage命令。
为了确保目录中的所有文件都具有正确的文件上下文,我们先运行semanage fcontext -l,再运行restorecon命令。在以下示例中,要注意在运行semanage和restorecon命令前后每个文件的文件上下文:
[root@host ~]# ls -Z /var/www/html/file*
unconfined_u:object_r:user_tmp_t:s0 /var/www/html/file1
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/file2
[root@host ~]# semanage fcontext -l
...output omitted...
/var/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
...output omitted...
[root@host ~]# restorecon -Rv /var/www/
Relabeled /var/www/html/file1 from unconfined_u:object_r:user_tmp_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
[root@host ~]# ls -Z /var/www/html/file*
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/file1
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/file2
以下示例显示了如何使用semanage为新目录添加上下文:
[root@host ~]# mkdir /virtual
[root@host ~]# touch /virtual/index.html
[root@host ~]# ls -Zd /virtual/
drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /virtual/
[root@host ~]# ls -Z /virtual/
-rw-r--r--. root root unconfined_u:object_r:default_t:s0 index.html
[root@host ~]# semanage fcontext -a -t httpd_sys_content_t 'virtual(/.*)?'
[root@host ~]# restorecon -RFvv /virtual
[root@host ~]# ls -Zd /virtual/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /virtual/
[root@host ~]# ls -Z /virtual/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
三、使用布尔值调整SELinux策略
1. SELinux布尔值
SELinux布尔值是可更改SELinux策略行为的参数。SELinux布尔值是可以启用或禁用的规则。安全管理员可以使用SELinux布尔值来有选择地调整策略。
selinux-policy-doc软件包附带的SELinux man page中介绍了可用布尔值的用途。使用 man -k ‘_selinux’ 命令可以列出这些man page。
用于管理SELinux布尔值的命令包括: getsebool - 列出布尔值及其状态; setsebool - 修改布尔值; setsebool -P - 更改SELinux策略以使修改持久保留。semanage boolean -l将报告布尔值是否为持久值,并提供该布尔值的简短描述。
非特权用户可以运行getsebool命令,但只有超级用户才能运行semanage boolean -l和setsebool -P。
[user@host ~]$ getsebool -a
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
antivirus_can_scan_system --> off
antivirus_use_jit --> off
...output omitted...
[user@host ~]$ getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
[user@host ~]$ setsebool httpd_enable_homedirs on
Could not change active booleans. Please try as root: Permission denied
[user@host ~]$ sudo setsebool httpd_enable_homedirs on
[user@host ~]$ sudo semanage boolean -l | grep httpd_enable_homedirs
httpd_enable_homedirs (on , off) Allow httpd to enable homedirs
[user@host ~]$ getsebool httpd_enable_homedirs
httpd_enable_homedirs --> on
-P选项可将所有待定值写入策略,使其在重启后待久保留。在下例中,要注意括号中的值:二者现在都设为on。
[user@host ~]$ setsebool -P httpd_enable_homedirs on
[user@host ~]$ sudo semanage boolean -l | grep httpd_enable_homedirs
httpd_enable_homedirs (on , on) Allow httpd to enable homedirs
要列出当前状态与默认状态不同的布尔值,要运行semanage boolean -l -C。
[user@host ~]$ sudo semanage boolean -l -C
SELinux boolean State Default Description
cron_can_relabel (off , on) Allow cron to can relabel
四、调查和解决SELinux问题
1. 对SELinux问题进行故障排除
在SELinux阻止访问服务器上的文件时(本该可以访问的),了解必须采取哪些操作至关重要。解决这些问题的步骤指南如下:
- 在考虑做任何调整之前,应了解到SELinux禁止意图访问的这一做法也许非常正确。当Web服务器尝试访问 /home 中的文件时,如果用户并未发布Web内容,则可能表明服务器遭入侵。如果已授予访问权限,则需要采取其他步骤来解决问题。
- 最常见的SELinux问题是使用不正确的文件上下文。此问题会在以下情况中发生:即,使用一个文件上下文在某个位置创建了文件,而该文件又被移至预期会使用其他上下文的地方。在大多数情况下,运行restroecon将会更正此问题。以这种方式更正问题对系统剩余部分的安全性具有非常小的影响。
- 对于严苛限制性访问的另一个补救措施可以是调整布尔值。例如,ftpd_anon_write布尔值控制匿名FTP用户能否上传文件。我们必须打开此布尔值以允许匿名FTP用户将文件上传到服务器。调整布尔值时需格外谨慎,因为布尔值会对系统的安全性造成广泛影响。
- SELinux策略可能存在阻止合法访问的漏洞。由于SELinux技术已经成熟,这种情况极少发生。一旦明确了某个策略漏洞,要联系红帽支撑并汇报此漏洞,以便问题得到解决。
2. 监控SELinux冲突
安装setroubleshoot-server软件包,以便将SELinux消息发送至 /var/log/messages。setroubleshoot-server 侦听 /var/log/audit/audit.log 中的审核消息,并发送简短摘要到 /var/log/message。该摘要包括SELinux冲突的唯一标识符(UUID),可用于收集更多信息。sealert -l UUID命令用于生成特定事件的报告。使用sealert -a /var/log/audit/audit.log命令可以在该文件中生成所有事件的报告。
考虑在标准Apache Web服务器上执行以下示例命令序列的情况:
[root@host ~]# touch /root/file3
[root@host ~]# mv /root/file3 /var/www/html
[root@host ~]# systemctl start httpd
[root@host ~]# curl http://localhost/file3
<!DOCTYPE HTML PUBLIC "~//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><bood>
<h1>Forbidden</h1>
<p>You don't have permission to access /file3 on this server.</p>
</body></html>
期望Web服务器提供file3的内容,但它却返回permission denied错误。查看 /var/log/audit/audit.log 和 /var/log/messages 可以发现关于此错误的一些额外信息。
[root@host ~]$ tail /var/log/audit/audit.log
...output omitted...
type=AVC msg=audit(1392944135.482:429): avc: denied { getattr } for
pid=1600 comm="httpd" path="/var/www/html/file3" dev="vda1" ino=8980981
scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
...output omitted...
[root@host ~]# tail /var/log/messages
...output omitted...
Feb 20 19:55:42 host setroubleshoot: SELinux is preventing /usr/sbin/httpd
from getattr access on the file . For complete SELinux messages. run
sealert -l 613ca624-248d-48a2-a7d9-d28f5bbe2763
这两个日志文件都指出SELinux拒绝是问题所在。作为 /var/log/messages 输出的一部分,sealert命令可以提供一些额外信息,包括可能的修复方法:
[root@host ~]# sealert -l 613ca624-248d-48a2-a7d9-d28f5bbe2763
sealert命令的 Raw Audit Messages 部分包含来自 /var/log/audit.log 的信息。要搜索 /var/log/audit.log 文件,则使用ausearch命令。-m将按消息类型执行搜索。-ts选项则根据时间执行搜索。
3. Web控制台
如果安装了Web控制台,它也可以用于对SELinux问题进行故障排除。登录Web控制台并从左侧的菜单中选择SELinux。SELinux策略窗口会通知我们当前的执行策略。所有的问题都会在SELinux Acces Control Errors部分进行详细说明。
单击 > 字符显示错误详细信息。单击solution details显示所有详细信息及可能的解决方案。
一旦问题得到解决,SELinux Access Control Errors部分便不再显示错误。如果显示消息No SELinux alerts,则说明所有问题均已解决。