认证目标4.05 安全增强型Linux入门
SELinux(Security-Enhanced Linux)是由美国国家安全局开发的安全增强型Linux,目的是提供强制访问控制级别。它的安全性能优于通过文件权限和ACL实现的自主访问控制。实质上,SELinux强制在操作系统的内核中实施安全规则。当系统安全受到破坏时,SELinux尽量控制其影响。例如,当FTP服务的系统账户受到危害时,SELinux会使用此账户危害其他服务的意图更难实现。
4.5.1 SELinux的基本功能
SELinux安全模型基于主题、对象和动作。主题是一个进程,如正在执行的命令,或在Apache服务器中正在运行的应用程序。对象就是文件、设备、套接字,或者推而广之,任何可被主题访问的资源。动作就是主题对对象执行的操作。
SELinux为对象分配不同的上下文。上下文就是一个标签,由SELinux安全策略用来决定是否允许在对象上执行主题的动作。
例如,Apache Web服务器进程可以接收网页文件等对象,并把它们显示给世界各地的客户端浏览。只要这个对象文件拥有合适的SELinux上下文,则这个动作在SELinux的RHEL 7实现中是允许的。
SELinux的上下文是非常严格的。换言之,如果一个黑帽黑客闯入用户的系统并接管了用户的Web服务器,SELinux上下文会阻止这个黑客利用这个漏洞闯入到其他服务。
用lz -Z命令可以显示特定文件的上下文。例如,仔细检查这个命令的执行结果,如图4-10所示,它显示了作者之一的/root目录中的安全上下文。
图4-10 不同文件的SELinux安全上下文
正如本章的开头曾提到的,在RHCSA考试中,与SELinux有关共有5个认证目标。接下来我们将讨论如何实现这些目标。
4.5.2 SELinux的状态
RHCSA的认证目标要求,考生必须知道如何“为SELinux设置强制的(或许可的)(enforcing/permissive)模式”。SELinux可以使用3个模式:强制模式(enforcing)、许可模式(permissive)和禁用模式(disabled)。强制模式和禁用模式的含义不言自明。许可模式是指,所有不符合的SELinux规则都保存在日记中,但是此违反事件不会阻止任何动作。
假如我们想要修改SELinux的默认模式,则需要修改/etc/selinux/config文件中的SELINUX指令,如表4-10所示。下次系统启动后,这些修改就会应用于系统。
表4-10 /etc/selinux/config文件中的标准指令
实际经验
在RHEL 6中,SELinux配置变量定义在/etc/sysconfig/selinux文件中。在RHEL中,/etc/sysconfig/selinux是一个符号链接,指向/etc/selinux/config。
当SELinux配置为强制模式,它用两种方法保护系统的安全:目标模式(targeted mode)和mls模式。默认情况下是目标模式,它允许用户更加精细地自定义SELinux要保护的服务。与此相反,MLS模式利用为美国国防部开发的Bell-La Padula模型进一步提高保护级别。该模型根据/etc/selinux/targeted/setrans.conf文件的要求,支持c0和c3级的安全级别。虽然c3被认为“最高级保密”,但是可用的最高级保密可达c1023级。像这样细化的保密级别还没有完全开发成功,如果想进一步了解MLS,需要安装selinux-policy-mls RPM程序包。
实际经验
如果你只是想测试SELinux,则可以把它配置为许可模式。它就会记录任何违反安全的操作,但不会阻止任何操作。用SELinux管理工具很容易配置SELinux,也可以在/etc/selinux/config文件中设置SELINUX=permissive指令。如果正在运行审计服务(auditd service),则任何违反安全的操作都会记录在/var/log/audit目录的audit.log文件中。请记住,Red Hat可能会要求考生在考试期间把SELinux配置为强制模式。
4.5.3 在命令行配置SELinux
虽然SELinux仍在不断发展,但是随着RHEL 6和RHEL 7的发布,它变得越来越有用。然而考虑到SELinux的复杂性,对于不是十分熟悉它的系统工程师来说,用SELinux管理工具(SELinux Administration Tool)配置SELinux参数可能会更加高效。
为此,接下来将介绍如何在命令行接口配置和管理SELinux。但是,由于用GUI工具更容易显示SELinux的全部功能,因此本章后面将详细介绍这些功能。
4.5.4 配置基本的SELinux设置
有几个重要的命令可用来检查和配置基本的SELinux设置。为查看SELinux的当前状态,执行getenforce命令。它返回三个选项中的一个:enforcing、permissive和disabled(这些选项不需要多加解释)。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 Policy MLS status: enabled Policy deny_unknown status: allowed Max kernel policy version: 28
用setenforce命令可以改变SELinux的当前状态,它的选项也是容易理解的:
# setenforce enforcing # setenforce permissive
上述命令会改变/sys/fs/selinux/enforce布尔值。作为布尔型参数,我们可以用1和0替换enforcing和permissive。如果要使修改永久生效,必须修改/etc/selinux/config文件中的SELINUX变量。但如果要具体修改SELinux各个布尔型参数,则需要不同的命令。
如果由于某些原因SELinux被禁用,则输出结果如下:
SELinux status: disabled
此时setenforce命令不会起作用。相反,需要在/etc/selinux/config文件设置SELINUX=enforcing。这需要重启系统才能“重新赋予标签(relabel)”,这里SELinux标签需要应用于本地系统上的每个文件。
考试提示
如果SELinux已被禁用,则在把SELinux设置为强制模式之后,重新引导系统需要好几分钟才行。尽管如此,它的引导过程并没有像以前版本的RHEL系统那样费时。
4.5.5 为SELinux配置普通用户
为查看当前SELinux用户的状态,执行semanage login -l命令。根据RHEL 7的默认安装模式,它会输出如下结果:
Login Name SELinux User MLS/MCS Range Service __default__ unconfined_u s0-s0:c0.c1023 * root unconfined_u s0-s0:c0.c1023 * system_u system_u s0-s0:c0.c1023 *
换言之,普通的“默认”用户也拥有与root用户相同的SELinux用户上下文。为了证实这一点,以普通用户身份运行id -Z命令。不改变其他条件,则这个命令输出以下结果,它表示此用户不受任何SELinux设置的限制。
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
上面的字符串定义了SELinux中的标签。标签由几个上下文字符串组成,字符串之间用列分开:用户上下文(以_u结束),角色上下文(以_r结束),类型上下文(以_t结束),机密性上下文和一个类别集。目标策略(在RHEL 7中是默认的SELinux策略)的规则常与类型(_t)上下文关联。
虽然这不属于考试要求的范围,但是普通用户必须受到SELinux的控制。当用户账户被破坏或者将要被破坏时,我们希望因此造成的损失会受到SELinux规则的限制。下面这个示例限制了添加(-a)普通用户michael,并为这种约束定义(-s)user_u上下文。
# semanage login -a -s user_u michael
user_u角色不能执行第8章中介绍的su或sudo命令。如有必要,可以用semanage -d michael命令取消这个设置。由于用户角色仍然还在发展,因此必须注意出现在最新Red Hat文档中各种可用的用户上下文,如表4-11所示。
表4-11 SELinux User Roles(用户角色)的选项
另一个常见的“用户”上下文是system_u,它通常不能应用于普通用户。当把ls -Z命令作用于系统和配置文件时,在其输出结果中经常会看到这个角色。
当一个用户角色发生变化时,只有等到下次登录后才会生效。例如,假如在基于GUI的命令行中把michael用户的角色改为user_u,则只有退出系统再登录到GUI环境此修改才会生效。当你在自己的系统上测试这个命令时,将不能启动任何管理配置工具,也不能使用su和sudo命令。
在某些网络中,我们可能希望把未来用户的角色改为user_u。但如果不希望普通用户盲目操作管理工具,则可以用下面的命令修改这些未来默认用户的角色:
# semanage login -m -S targeted -s "user_u" -r s0 __default__
这个命令修改(-m)了目标策略存储(-S),把SELinux用户设置为(-s)user_u角色,并给默认用户设置了MLS s0安全级(-r)。其中的“__default__”的两侧都包含两个下划线。只要user_u角色对默认的SELinux用户有效,则普通用户就无法使用管理工具或者诸如su和sudo的命令。下面这个命令取消前面的设置:
# semanage login -m -S targeted -s "unconfined_u" \ -r s0-s0:c0.c1023 __default__
由于unconfined_u用户通常不受MSL安全的限制,因此这里需要全部的MLS安全级范围(s0-s0:c0.c1023)。
考试提示
MLS模式增加了SELinux的复杂性。给目标默认策略设置正确的布尔型参数和文件上下文,通常会提供超出平常需要的安全设置。
4.5.6 管理SELinux布尔型设置
大多数SELinux设置都是布尔型——换言之,它们都可以用1和0值表示启动和禁用。这些参数一旦设置好,就保存在/sys/fs/selinux/booleans目录中。一个简单示例是selinuxuser_ping,这个参数通常置为1,它允许用户执行ping命令和traceroute命令。很多SELinux设置都与特定的RHCE服务有关,因此将在本书后半部分讨论。
用getsebool可以读取这些设置的值,用setsebool命令可以修改它们的值。例如,下面的内容是getsebool user_exec_content命令的输出结果,它说明SELinux允许用户执行自己主目录中或/tmp目录中的脚本:
user_exec_content --> on
这个默认设置应用于SELinux user_u用户。换言之,利用这个布尔型参数,这些用户可以在前面提到的目录中创建和执行脚本。这个布尔型参数可以暂时被禁用,或者在系统重新启动后保留下来。可以使用setsebool命令来达到上述目的。例如,下面的命令禁用刚才提到的这个布尔型参数,直到系统下次重新启动为止:
# setsebool user_exec_content off
在这个命令中可以用=0替换off,由于这是一个布尔型设置,替换后的效果是一样的。但为使这个布尔型设置的修改值在系统重新启动后仍然有效,必须使用-P选项。注意,只有等该用户实际登录到相关的系统后,这个修改才会起作用。
用getsebool -a命令可以显示全部可用的布尔型参数列表。
想了解每个布尔型参数的更多信息执行semanage boolean -l命令。这个命令的输出包含了全部可用的布尔型参数的详细说明,它是一个可以用grep命令进行搜索的数据库。
4.5.7 显示和识别SELinux文件上下文
如果已经启动了SELinux,则用ls -Z命令可以列出当前SELinux文件上下文,如前面的图4-10所示。作为一个示例,我们只列出与/root目录中的anaconda-ks.cfg文件有关的输出结果:
-rw-------. root root system_u:object_r:admin_home_t:s0↲ anaconda-ks.cfg
输出结果中包含了普通的ugo/rwx所有权和权限数据,也指定了SELinux安全的四个元素:指定文件的用户、角色、类型和MLS级别。一般说来,文件的SELinux用户是system_u或unconfined_u,而这通常不会影响访问。大多数情况下,文件与object_r有关,后者是文件的一个对象角色。当然在SELinux目标策略的未来版本中,用户和角色可能会包含更多的细分选项。
主要的文件上下文是类型。此处即为admin_home_t。在第1章配置FTP和HTTP服务器时,为了与这些服务的共享文件的默认类型相匹配,我们用chcon命令修改了配置目录和目录中文件的类型。
例如,为给一个FTP服务器配置一个非标准的目录,必须使它的上下文与默认的FTP目录相匹配。考虑下面的命令:
# ls -Z /var/ftp/ drwxr-xr-x. root root system_u:object_r:public_content_t pub
上下文是系统用户(system_u)和系统对象(object_r)、类型为与公开用户共享(public_content_t)。如果我们给这个FTP服务创建了另一个目录,则需要把同样的安全上下文赋给此目录。例如,如果我们以root管理员身份创建/ftp目录并且执行ls -Zd /ftp命令,则会看到这个/ftp目录的上下文:
drwxr-xr-x. root root unconfined_u:object_r:root_t /ftp
为修改这个目录的上下文,可以使用chcon命令。如果它们是一些子目录,必须使用-R选项确保可以递归地应用所有修改。这里为了修改用户和type上下文使之与/var/ftp相匹配,需要执行以下命令:
# chcon -R -u system_u -t public_content_t /ftp
如果我们想支持上传到FTP服务器,则需要给它分配不同类型的上下文,具体来说需要指定public_content_rw_t选项。相应的命令如下:
# chcon -R -u system_u -t public_content_rw_t /ftp
第1章已经使用过chcon命令的另一种形式。为使用那里的内容,下面的命令将用到/var/ftp目录上的user、role和上下文,并将这些修改递归地应用于/ftp目录。
# chcon -R --reference /var/ftp /ftp
但是,如果文件系统被重新赋予标签,会发生什么?使用chcon做出的修改在文件系统重新赋予标签后不会保存,因为所有的文件上下文将被重置为SELinux策略中定义的默认值。因此,我们需要有一种方法,以修改定义了每个文件的默认文件上下文的规则。下一节将介绍这个主题。
实际经验
使用restorecon是修改文件上下文的首选方式,因为它将上下文设置为SELinux策略中配置的值。chcon命令可以将文件上下文修改为参数中传递的任何值,但是如果上下文不同于SELinux策略中定义的默认值,那么文件系统被重新赋予标签后,使用chcon所做的修改不会保存。因此,为了避免犯错,应该使用semanage fcontext修改SELinux策略中的上下文,使用restorecon修改文件的上下文。
4.5.8 恢复SELinux文件上下文
在/etc/selinux/targeted/contexts/files/file_contexts文件中可以配置默认的上下文。当我们操作出错并想恢复一个文件原来的SELinux设置,则restorecon命令可以根据file_contexts配置文件恢复这些设置。但是目录的默认参数值可能会不一样。例如,下面这个命令(-F开关选项强制修改所有上下文,而不只是类型上下文)会给/ftp目录分配一组不同的上下文。
# restorecon -F /ftp # ls -Zd /ftp drwxr-xr-x. root root system_u:object_r:default_t ftp
注意,user上下文不同于/ftp目录刚创建时的上下文。这是由于前面提到的file_contexts文件的第一行的原因,这一行应用前面提到的上下文。
/.* system_u:object_r:default_t:s0
使用semanage fcontext -l命令可列出file_contexts中的所有默认文件上下文。图4-11是其输出的一段节选。
图4-11 SELinux上下文的定义
可以看到,SELinux上下文定义使用了正则表达式,例如:
((/.*)?
这个正则表达式匹配/字符,后跟任意数量的字符串(.*)。?字符的意思是,括号内的整个正则表达式可被匹配0次或1次。因此,总体结果是匹配/后跟任意数量的字符,或者匹配什么都没有的情况。这个正则表达式被广泛用于匹配一个目录及其包含的所有文件。
举个例子,下面这个正则表达式可匹配/ftp目录及其中的所有文件:
/ftp(/.*)?
通过使用这个正则表达式,可以定义一个SELinux策略规则,为/ftp目录及其中的所有文件分配一个默认的类型上下文。这可以使用semanage fcontext -a命令完成。例如,下面的命令将默认的类型上下文public_content_t分配给/ftp目录及其中的所有文件:
# semanage fcontext -a -t public_content_t '/ftp(/.*)? '
当为文件系统路径定义了新的默认策略上下文后,可以运行restorecon命令,将上下文设为对应的默认策略值。下面的命令以递归方式(-R)将上下文恢复为前面定义的public_context_t值:
# restorecon -RF /ftp # ls -Zd /ftp drwxr-xr-x. root root system_u:object_r:public_content_t ftp
4.5.9 识别SELinux进程上下文
正如第9章将要指出,ps命令可以显示当前正在运行的进程。在SELinux系统中,每个运行的进程都有上下文。为了查看当前所有运行进程的上下文,可以执行ps -eZ命令,它列出每个(-e)进程的SELinux上下文(-Z)。图4-12是在我们的系统上执行此命令的一段输出结果。
图4-12 不同进程的SELinux安全上下文
尽管用户和角色不会经常改变,但是进程的类型变化很大,这是为了与运行进程的目的相匹配。例如,从图的底部Avahi守护进程(avahi-daemon)与avahi_t SELinux类型匹配。你至少可以识别部分SELinux类型与相应的服务相匹配。
换言之,虽然SELinux类型各不一样,但是它们都与正在运行的进程相一致。
4.5.10 诊断和处理违反SELinux策略的事件
如果出现一个问题且SELinux正在强制模式下运行,而且确信目标服务或应用程序不会存在问题,则不要禁用SELinux! Red Hat已简化了SELinux的管理和故障处理。根据Red Hat,引起SELinux相关问题的两个主要原因是上下文和布尔型设置。
1. SELinux审计
SELinux遇到的问题都会保存在相关的日志文件,即/var/log/audit目录中的audit.log文件中。这个文件很容易迷惑人,第一次看到它更是如此。现在有许多工具可用来解释这个日志文件。
首先,审计搜索命令(ausearch)命令可以帮助我们过滤某些特定类型的问题。例如,下面的命令列出所有与使用sudo命令有关的SELinux事件:
# ausearch -m avc -c sudo
这些事件也称为访问向量缓存(Access Vector Cache, AVC)(-m avc)消息,-c选项允许我们定义通常在日志中使用的名字,如httpd或su。如果已经试验过本章前面介绍的SELinux用户user_u,则在audit.log文件中有几个消息与这个用户有关。
即使对大多数管理员而言,这个输出列表也是也显得过于冗长。但是它包含了一些标识信息,如被审计的用户ID(显示为auid),用它可以确定发出攻击的用户。也许用户正需要这样的访问,也许此用户账户已受到破坏,不管哪种情况,这警告我们要更多地注意这个账户。
相反,sealert -a /var/log/audit/audit.log命令可能会提供更容易理解的列表,图4-13是其中的一个片段。
图4-13 一个SELinux警告
2. SELinux标签和上下文问题
考虑图4-13以及到目前为止介绍的SELinux概念,你可能想知道出现问题的用户能否允许执行su命令。假如这个问题出现在第8章要介绍的/etc/sudoer文件中,则SELinux警告消息甚至不会出现。因此必须特别注意源和目标上下文。如果两者相匹配,则文件上下文不是问题。
通过排除法表明前面提到的用户上下文就是这个问题的原因。出现问题的用户的UID必须出现在这个文件后面的“Raw Audit Message”(原始审计消息)段中。如果上述用户需要访问su和sudo命令,则必须用semanage login命令修改此用户的角色。否则说明此用户可能正在测试Linux。任何对sudo命令的访问都会记录在/var/log/secure日记文件中。
3. SELinux的布尔型问题
在禁用了前面提到的user_exec_content布尔型后,我们为由user_u标签控制的用户创建了一个简单的脚本script1。在把该脚本变成可执行文件后,我们试图用/home/examprep/script1命令执行这个脚本文件。尽管这个用户是这个文件的所有者,并且拥有可执行权限集,但这个尝试得到了以下消息:
-bash: /home/examprep/script1: Permission denied
这就得到如图4-14所示的一段日志。注意顶部的一段,它清楚地列明了处理这个问题需要使用的命令。作为系统管理员,我们需要决定是否允许这样的用户拥有执行自己脚本的权限。如果是,则上述命令可以解决这个问题。
图4-14 一个SELinux警告和解决办法
4.5.11 GUI SELinux管理工具
如果已经花了一些时间学习命令行的SELinux,则本节只是一个概述。对许多用户而言,修改SELinux设置的最简单方法是使用SELinux管理工具。这个工具可以用system-config-selinux命令启动。如图4-15所示,它先显示本地系统上SELinux的基本状态,这些状态的信息反映在sestatus命令的输出列表中。
图4-15 管理工具中SELinux的状态信息
正如读者所见,默认和当前的强制模式都有几个选项,我们可以把它们设置为Enforcing、Permissive或Disabled。虽然,SELinux的重点在于目标策略(Targeted policy),但是如果安装了selinux-policy-mls程序包,则MLS也是可以使用的。通常情况下,我们不必激活Relabel On Next Reboot选项,除非我们已经修改了默认的策略类型。
SELinux Management Tool窗口的左侧窗格中有许多类别,这些类别将在稍后介绍。在本书的RHCE部分,还要讨论这个工具,但是重点是关布尔型参数的设置。
1. SELinux布尔型设置
在SELinux管理工具中,单击左侧窗格中的Boolean,翻卷可用的模块。正如读者所见,SELinux策略可以在许多不同的类别中修改,有些与管理功能有关,还有的与一些特定服务有关。图4-16显示了这些选项的选取情况。在这里所做的任何修改都会反映到/sys/fs/selinux/booleans目录中的布尔型变量。对于RHCSA考试来说比较重要的模块类别有cron、mount、virt和包含一切的模块类型:unknown。这个列表比较短,相关的布尔型参数显示在表4-12中,它们按在SELinux管理工具中的顺序进行排列。
表4-12 部分SELinux布尔型参数
图4-16 SELinux管理工具中的布尔型参数
2.文件标签(File Labeling)
我们可以修改文件的默认标签,其中部分标签已在本章前面介绍过(其他几章中将要介绍SELinux上下文)。图4-17列出其中一些标签的选项。在这个窗口中所做的任何修改都要写入/etc/selinux/targeted/contexts/files目录中的file_contexts.local文件。
图4-17 在SELinux管理工具中的文件类型
3.用户映射
在User Mapping(用户映射)组中,我们可以为普通用户和管理员用户设置默认参数以外的参数。这里显示的内容说明了semanage login -l命令的当前结果。如果无法记住semanage命令错综复杂的选项,则使用这个屏幕可以比较容易地建立起现有用户到不同上下文之间的映射关系。单击Add按钮打开如图4-18所示的Add User Mapping窗口。此图也说明如何把名为michael用户重新归类为SELinux的user_u用户类型。
图4-18 在SELinux管理工具中建立用户映射
4. SELinux用户
SELinux User允许我们为标准的用户定义和修改默认的角色。标准用户包括普通用户(user_u)、系统用户(system_u)和不受限制用户(unconfined_u)。
5.网络端口
Network Port在标准端口与服务之间建立关联。
6.策略模块
Policy Module定义了应用于每个模块的SELinux策略版本号。
7.进程域组
Process Domain允许我们针对单个进程域(而不是整个系统)把SELinux的状态改为允许模式或强制模式。
4.5.12 SELinux故障排除浏览器
RHEL 7包含了SELinux故障排除浏览器(SELinux Troubleshoot Browser),如图4-19所示。它为经常遇到的问题提供帮助和建议,并使用大多数Linux管理员能理解的语言,通常还包含用户可以运行的能解决相关问题的命令。
图4-19 SELinux故障排除浏览器中的安全警告
要在GNOME桌面上启动这个浏览器,选择Applications | Sundry | SELinux Troubleshooter,或者在GUI的命令行中执行sealert -b命令。此命令由setroubleshoot-server程序包提供。
4.5.13 练习4-3:测试SELinux用户类型
在本练习中,要把一个用户配置为staff_u SELinux用户类型并测试配置结果。你需要一个GUI工具,除root管理员用户外至少还需要一个普通用户。
(1)如有必要,创建一个普通用户。即使已经有一个普通用户,在本练习中创建第二个普通用户可以减少风险。用户总是可以删除的,这将在第8章中讨论。为此用useradd user1命令创建一个用户,用passwd user1命令给此用户设置口令。
(2)用semanage login -l命令检查当前用户的SELinux类型。
(3)用semanage login -a -s staff_u user1命令把上述用户配置为staff_u用户。根据实际情况替换其中的user1。
(4)如果已完全登录到GUI,则先退出。选择System | Log out命令,在随后出现的窗口中单击Log Out按钮。
(5)以刚修改过的staff_u账户即user1(或者其他在步骤(3)中配置的名字)登录到GUI。如果没有看到GUI登录屏幕,按ALT+F1或ALT+F7。
(6)尝试各个管理命令。访问su命令了吗?sudo命令呢?如果不知道如何使用sudo命令,可以在阅读第8章后回过头看这个练习。本书到目前为止介绍的哪些管理工具可以访问?从GUI命令行启动这个工具与从GUI菜单启动它是否有区别?
(7)退出新建的user1账户,重新以普通用户身份登录到系统。
(8)从staff_u列表中删除新创建的用户。如果这个用户是user1,则执行semanage login -d user1命令也可以删除这个用户。
(9)用semanage login -l命令验证配置是否已恢复。