本系列 前一篇 主要介绍了 Linux 权限管理和访问控制的相关概念与 DAC 相关的 UGO+RWX、ACL,本篇续写 MAC 相关概念与知识,主要详细介绍 SELinux。
1. 强制访问控制(SELinux)
前半部分讲解了Linux系统中实现的DAC(Discretionary Access Control,自主访问控制)机制,主要包括传统的UGO+RWX
机制和 ACL 机制;下半部分开始讲解MAC(Mandatory Access Control,强制访问控制),该部分主要讲 SELinux,因为 Linux 系统中的MAC机制,主要由 SELinux 来实现。
2. SELinux简介
2.1 起源
NSA(美国国家安全局)一直非常关注计算机操作系统的安全领域,他们发现大部分操作系统的安全机制,包括Window和大部分*nix系统,都是以DAC机制为安全认证基础的。由于DAC机制的设计很不利于系统安全,NSA便一直致力于开发一套更安全的MAC操作系统安全认证机制。
DAC与MAC两种安全机制的原理与区别,在前文已叙述过,DAC的控制方式够灵活,比较松,但不严格,有一定的安全隐患。在DAC的控制机制中,传统Linux由于 root
权限的“权力”过大而造成巨大的安全威胁:一旦黑客入侵Linux操作系统并获得root
权限,整个操作系统将暴露于恶意攻击的威胁之下。
SELinux 正是为解决这类为题而设计,它控制了无限的root
权限,并不采用大众所知道的传统安全机制。在SELinux下,root
账号采用强制访问控制机制,同时限制用户和程序(主体)使用最低权限做足以完成任务的工作。因此,即使系统不幸遭受黑客攻击,由此引起的危害也随之降到最低限度,所以极大地提升了Linux系统的安全性。
2.2 SELinux 工作机制概述
在SELinux中,每个对象(程序、文件和进程等,包括前文所述的“主体”与“客体”)都有一个 安全上下文(Security Context),它依附于每个对象身上,记载着该对象具有的权限(SELinux定义的权限)。管理员可以通过定制 安全策略(Security Policy)来定义这些安全上下文,从而定义哪种对象具有什么权限。当一个对象需要执行某个操作时,系统会按照该对象以及该对象要操作的对象的安全上下文所定制的安全策略来检查相对应的权限,去过全部权限都符合,系统就会允许该操作,否则将阻断这个操作。这些过程不会影响到其他正常运行的对象,系统会保证它们的安全系统结构以及稳定运行。
SELinux 从Linux Kernel 2.6开始,就已经是内核的一部分了;传统的 UGO+RWX
机制也是运行在内核中;ACL 是一个POSIX标准。
在启用了SELinux的Linux操作系统中,某个对象需要执行某个操作时,系统权限管理不仅根据安全上下文所规定的内容来检查,同时还要根据传统DAC机制来检测,并且是先通过DAC机制的检测,再由SELinux定制的安全策略来检测。只有通过DAC和SELinux的双重检测之后,才能执行操作。
SELinux 的另一个重要概念是 TE(Type Enforcement,类型强制),其原理是将权限与程序的访问结合在一起,而不是结合用户。本文讨论的所有SELinux策略特性,都是处理主体(运行中的进程)对客体(文件、目录或套接字等)的访问权的,主要集中于程序访问控制决策,这也是SELinux的主要功能。它允许SELinux安全策略编写者基于程序的功能和安全属性,加上用户要完成任务所需的访问权作出访问决策,可以将程序限制到功能合适、权限最小化的程度。因此,即使它出现了故障或被攻击,但整个系统的安全并不会受到威胁。例如,一个Web服务器的策略阻止修改它显示的文件,那么即使Web服务器被攻破,TE策略也能阻止被攻破的服务器修改那些文件。这样就消除了通过Web服务器的漏洞攻击造成对整个服务器的威胁,而只有被攻破的应用程序受到影响,并且它会被我们的安全策略限制访问权限。
具体的系统运行中,在 SELinux 系统启动时,会加载一个叫做policy.*
的安全策略配置文件,这个文件中就定义了SELinux设定的各种权限。如果用户在文件中设定了SELinux不能在开机后转回 permissive
模式的话,那么系统的root
用户则可能无法修改当前的设定,也就是说root
用户在SELinux中已经不具有默认的所有权限。因此,即便黑客盗取了root
用户密码并成功入侵到用户的计算机,也只能在他入侵的这个自治域内进行破坏,并不会像以前那样扩散到整个Linux系统。因此,在启用了SELinux的Linux操作系统中,root
用户也被限制进行某些操作。
2.3 SELinux 的优势
总的来说,SELinux有以下几点优势:
- 所有的进程与文件都用一个类型(Type)来标记。一个类型定义了一个进程的域(Domain)和一个文件的域。不同的进程只在自己所属的域内运行,SELinux的策略则定义了不同进程与文件、进程与进程间通信的方式。只有SELinux的策略允许,一个访问操作才可能被执行;
- 细粒度访问控制。优于传统的基于用户和组的Linux自主访问控制机制,SELinux基于一切可用信息,比如SELinux定义的用户、角色、类型和一个可选的安全等级;
- SELinux策略是以管理方式定义的、全系统范围内有效的,不是用户自主可控的;
- 降低提权攻击的风险(上面所讲述的SELinux的主要贡献就是这个);
- SELinux 可以保证数据的机密性和完整性,并能防止部分外部恶意数据输入。
但是,需要注意以下几点:
- SELinux 不是防病毒软件,也不能替代防病毒软件;
- SELinux 不能替代基础密码、防火墙或者IDS/IPS或者其他安全防护系统;
- SELinux 不是一体化的防护系统。
3. SELinux 基本工作原理
3.1 SELinux 中的上下文(Context)
SELinux 系统中的进程和文件都标记了 SELinux 的上下文,这个上下文包含了许多有用的信息,包括SELinux用户(不同于Linux系统的用户)、角色(Role)、类型(Type)和级别(Security Level)等等。在运行 SELinux 的时候,这些上下文信息被用来辅助进行访问控制,它们可以看做是 SELinux 策略的“维度”。最新的 SELinux 综合提供了 RBAC、TE(类型增强)和 MLS(Multi-Security Level,多级别安全)三种访问控制机制。
下面是一个 SELinux 上下文的例子。SELinux 上下文广泛使用在 进程、Linux用户、文件中,使用 ls -Z [file|dir]
命令可以查看文件或目录的 SELinux 上下文:
SELinux 上下文的组成为:
SELinux user
SELinux user
标志一群被授权的角色或者一个特定的 MLS 范围。每一个 Linux 系统用户都通过 SELinux 机制被映射为一个 SELinux user
,这使得Linux用户可以继承 SELinux 用户的访问权限。这个标志主要用于限制 Linux 用户可以进入的角色和级别范围,相当于 SELinux 对 Linux 的用户结构进行了一层封装。
Linux 下用 root
用户权限运行 semanage login -l
命令可以查看 SELinux 用户与 Linux 用户之间的映射关系:
- 例子中第一列为 Linux 系统用户;
- 第二列的 SELinux 用户列出了第一列系统用户对应的 SELinux 用户。对于进程来说,这些 SELinux 用户直接限制了什么角色和级别可以为该用户访问;
- 第三列的 MLS/MCS 范围 则给出了 MLS 和 MCS(Multi-Category Security,多种类安全)机制所采用的 安全级别(Level)。关于 MCS 和 Level,下文详解;
- 最后一列的服务,定义了对应的Linux系统用户登录后对应的 SELinux 上下文,默认值
*
代表任意服务。
角色(Role)
SELinux 中有一部分采用前文介绍的基于角色的访问控制(RBAC)机制。而 role
是 RBAC 机制中的一个属性,也是 RBAC 机制在 SELinux 中的运用。在 SELinux 的设计中,Linux 系统用户被映射为 SELinux 用户,而 SELinux用户被授权为角色(Role),继而角色被授权为对应的可访问的域(Domain)。所以,角色作为域和 SELinux 用户之间联系的媒介。通过角色可以决定 SELinux 用户可以访问哪些域,而最终决定了SELinux 用户可以访问哪些对象类型。通过这种机制可以降低权限提升的风险。
类型(Type)
类型是类型强制(Type Enforcement)机制的一个属性,也是 TE 机制在 SELinux 中的实现。类型为进程定义了域,为文件定义了类型。SELinux 机制策略明确定义了类型间相互访问、域访问类型和域间相互访问的规则和许可。只有存在某条 SELinux 机制规则允许的情况下,才允许上述的访问发生。
级别(Level)
级别是上述 MLS 和 MCS 机制的另一个重要属性。一个 MLS 范围是一个 级别对,采用区间标志,比如 (最低级别, 最高级别)
或者 (S0, s5)
。每个级别都是一个种类(Category) 敏感的数对,然而种类是可选的。如果存在种类,则可以表示为 sensitivity: category-set
的形式,如果没有种类,则只用 sesitivity
表示即可。
如果种类集(category-set)是连续的,则在表示时可以简写,比如 c0.c2
与 c0,c1,c2
表示同样的含义。举例说明:在最新的 CentOS7
操作系统中,目标机制(Targeted Policy)对MCS进行了增强,因此它只有一个敏感级别 s0
。MCS 支持 1024 个不同的种类,从 c0
一直到 c1023
,所以,s0-s0:c0.c1023
所有的种类都被授权。
另外,与级别相关的 /etc/selinux/targeted/setrans.conf
配置文件非常重要,切记用 Vi(m)/Gedit/Nano/Emacs 等编辑器对其直接进行编辑,可以使用 semanage
命令进行修改,这样才能保证修改的正确性。
类型强制(Type Enforcement)
SELinux 策略大部分都是一套声明和规则一起定义的类型强制(TE)策略,一个定义良好、严格的 TE 策略可能包括上千条 TE 规则,TE 规则数量的巨大是正常现象,因为它们表达了由内核暴露出的允许对资源的访问权,这就意味着每个进程对每个资源的访问尝试都必须至少要得到一条 TE 规则的允许,考虑一下现代Linux操作系统中进程和资源的数量,就会明白为什么有这么多 TE 规则了。
TE 规则数量众多,但规则本身并不复杂,分类也较少,所有的规则基本上都属于两类范畴:访问向量(AV,Access Vector)和类型规则。AV规则允许或审核两个类型之间的访问权,而某些情况下使用类型规则控制默认的标记。
由于 TE 规则数量较多,全部加载比较耗费资源,每次检索也会比较费性能,所以,在 SELinux 运行的过程中,系统实现了一个 访问向量缓存(Access Vector Cache),用来存放已经查询过的规则,提高性能。
正如类型强制的名字所示,TE 规则通过安全上下文与所有资源结合起来对类型起作用,策略语言包括了另外的允许我们定义类型及其策略组件的语句。SELinux 不会管Linux系统用户,可以给同一个程序指定多个域类型(因此有不同的特权集),这样就允许引入角色的概念。因此,访问控制的标准仍然是基于程序的域类型而不是基于用户的域类型。
3.2 域转换(Domain Transitions)
前文介绍过,SELinux 一大特点就是将进程和用户的执行权限限定在一个域(Domain)内。因此,即使 root
用户也不可能具有太大权限,从而保证了系统整体的安全性。SELinux 中定义的 域
会限定进程的执行权限或范围,但进程执行的时候是可以从一个域转换到另外一个域的,以获得另外一个域内限定的权限。进程从一个域转换到另一个域需要执行一个具有新域的入口点(Entrypoint)权限的应用程序来实现。这个“入口点”许可在 SELinux 机制中使用,它用来控制某些应用程序可以用来进入一个域。为了清楚说明这个问题,下面举实例说明。
一个用户想要修改自己的密码。为了修改密码,应该运行 passwd
程序,/usr/bin/passwd
可执行命令的标记 passwd_exec_t
类型,如下:
在实际执行过程中,该命令访问了 /etc/shadow
文件,该文件的类型为 shodow_t
,如下:
SELinux 机制的相关规则规定:运行在 passwd_t
域(域,是 TE 机制为进程定义的权限范围;passwd_t
域,即是/usr/bin/passwd
程序运行时的进程所处的域)的进程对标记为 shadow_t
类型(类型,是 TE 机制为文件定义的权限范围)的文件具有读和写的权限。并且, shadow_t
类型仅仅只赋予和密码修改相关的那些文件,这些文件包括 /etc/gshadow
、/etc/shadow
以及它们的备份文件。根据这个规则,用户可以知道:passwd_t
域的进程具有 passwd_exec_t
类型的 入口点
权限。因此,当用户运行 /usr/bin/passwd
程序修改密码时,该程序启动的进程运行在 passwd_t
域;由于 passwd_t
域的进程可以对 shadow_t
类型的文件进行读写操作,所以 passwd
命令的进程可以操作 /etc/shadow
文件。
当然,在 SELinux 机制中,如果默认情况下(没有相应规则),该进程是无法访问相应文件的。可以进一步解释这个例子:未使用 SELinux 的 Linux 操作系统中,/usr/binpasswd
程序是可信的,因而可以修改经过加密的密码文件 /etc/shadow
。所以,passwd
程序执行它自己内部的安全策略,允许普通用户修改自己的密码,同时也允许 root
修改所有的密码。为了执行这个密码修改操作,passwd
程序需要有移动和重新创建shadow
文件的能力。在标准 Linux 系统中,它具有这个特权,因为 /usr/bin/passwd
在执行时被加上了 setuid
位,它作为 root
用户被允许对密码进行修改操作。然而,许多程序都可以作为 root
允许(实际上,所有程序都有可能作为 root
允许)。这就意味着任何程序(当以 root
身份运行时)都有可能修改 /etc/shadow
文件。因此,类型强制使用户能做的事情是确保只有 /usr/bin/passwd
程序(或类似受信程序)可以操作 /etc/shadow
文件,而不论运行程序的用户是谁。
在上述例子中,除 SELinux 的相关规则约定外,TE 机制在很大程度上保证下面几条前提条件:
- 只有标记为
passwd_exec_t
类型的应用程序执行才能进入passwd_t
域,其他的命令执行时都不允许进入该域; - 只有一些授权的域,比如
passwd_t
才能对shadow_t
类型的文件具有读写权限。及时其他的进程具有超级用户的权限,也不允许对shadow_t
类型的文件具有写权限,因为它们并不运行在passwd_t
域中; - 只有一些授权的域才能转换到
passwd_t
域,比如sendmail
进程运行在sendmail_t
域中,在该域中它们没有合理的理由和权限执行passwd
命令,因此就不授予转换到passwd_t
域的入口点; - 运行在
passwd_t
域中的进程只对授权的类型具有读写权限,例如标记为shadow_t
和etc_t
类型的文件。这就有效阻止了passwd
命令对其他文件的任意读写权限,从而保证了最小权限运行,最终保证了系统安全。
3.3 SELinux 中进程上下文
前文所述的上下文是以文件上下文来说的,其实,SELinux机制的实现中,还有进程上下文和用户上下文,下面分别介绍一下。
前文讲过用命令 ls -Z [file|dir]
可以查看文件上下文,类似地,用命令 ps -eZ
就可以查看进程上下文:
3.4 SELinux 中用户上下文
类似地,id -Z
命令可以查看Linux系统用户相关的SELinux上下文信息:
4. 使用 SELinux 前的准备工作
4.1 SELinux 相关的工具
前文已经使用了 semanage
命令来查看 Linux 系统用户与 SELinux User 之间的映射关系,其实,与 SELinux 相关的工具包与命令工具有好多。安装系统时默认也安装了一些基础的命令工具,但CentOS7 系统如果以最小化的文字模式安装,policycoreutils-python
包和 policycoreutils-gui
包是不会被安装的,里面附带的一些工具也不可用,或者下面列表中其他默认不被安装的工具包,都需要用 yum install [package_name]
来手动安装。下面是常用的工具包及其里面的工具简介:
- policycoreutils:提供与 SELinux 相关的命令,比如
restorecon
,secon
,setfiles
,semodule
,load_policy
和setsebool
来操作和管理 SELinux。 - policycoreutils-gui:提供图形化软件
system-config-selinux
来管理 SELinux。 - policycoreutils-python:提供命令比如
semanage
,audit2allow
,audit2why
, 和chcat
来管理和操作 SELinux。 - selinux-policy:提供 SELinux 引用策略,该引用策略包括了所有的 SELinux 策略,并被用作其他策略(如 Targeted Policy)的基础使用。
- selinux-policy-targeted:提供 SELinux 的
targeted
策略。 - selinux-policy-mls:提供 SELinux 的
MLS
策略。 - setroubleshoot-server:翻译 SELinux 的拒绝操作体质信息,为
sealert
工具提供可以查看的、可读性好的信息。 - setools/setools-console/setools-gui:这些安装包提供了与 SELinux 相关的策略分析、检索、日志审计与监控、文件上下文管理管理的相关工具。setools是元工具,setools-gui提供了
apol
,seaudit
工具;setool-console 则提供了sechecker
,sediff
,seinfo
,sesearch
, 和findcon
等命令行工具。 - mcstrans:提供对 SELinux 上文中的级别(比如
s0-s0:c0.c1023
)翻译的工具。 - libselinux:为 SELinux 的应用提供 API 支持。
- libselinux-python:为 SELinux 应用提供 Python 绑定接口。
- libselinux-utils:提供
avcstat
,getenforce
,getsebool
,matchpathcon
,selinuxconlist
,selinuxdefcon
,selinuxenabled
, 和setenforce
工具。
上述工具的使用请自行查阅相关资料。
4.2 SELinux 日志
SELinux 有不止一种日志文件可记录在运行过程中对操作的拒绝日志,以便管理员后续审计与分析。默认情况下,CentOS7 安装了 dbus
和 audit
服务,另外一个有用的 SELinux 日志相关的工具包 setroubleshoot-server
可用命令 yum install setroubleshoot
来安装。
如果 audit
守护进程在运行,SELinux 的拒绝操作日志便会记录在 /var/log/audit/audiut.log
中,内容如下所示:
如果 setroubleshooted
进程在运行的话,上面的记录将会被翻译成可读性好的形式保存到 /var/log/messages
中:
当然,不同形式的拒绝操作信息被保存到不同的文件中,是根据不同的守护进程耳钉的,下表列出了对应不同的守护进程的日志文件路径:
守护进程 | 日志文件 |
---|---|
audit [on] |
/var/log/audit/audit.log |
audit [off]/rsyslogd [on] |
/var/log/messages |
setroubleshooted /rsyslogd /audit [on] |
/var/log/audit/audit.log 翻译后存入 /var/log/messages |
至于上述 3 个进程的启动、随系统启动自动启动的设置,请查看 systemd
相关的 systemctl
命令用法。
5. SELinux 目标策略
前文讲了 SELinux 基本的工作原理,主要是对 Linux 系统用户、文件以及进程“标记”上 SELinux 定义的上下文,然后根据 SELinux 策略对不同的上下文元素进行分域、分等级、分角色和分类控制。
接下来的内容是 SELinux 的第二部分核心内容:策略 。SELinux 的策略以配置文件形式存在,并且有不同的策略用于不同的功能。这一部分就以最常用的目标策略(Targeted Policy)为例开始讲解 SELinux 中关于 策略 的方方面面。
5.1 Targeted Policy 原理
Targeted Policy 是从 strict 示例策略衍生而来的,它们结构与组织几乎相同。不同的是 strict 策略更趋向于最大化使用 SELinux 所有特性,为大部分程序提供强大的安全保护;而 Targeted Policy 的目标是隔离高风险程序。Targeted Policy 的好处是,一方面可以向 Linux 系统添加大量的安全保护,同时又尽量少影响现有的用户程序。Targeted Policy 的策略主要集中于面向网络的服务(即那些暴露在外容易遭受黑客攻击的组件与服务),Targeted Policy 是 RHEL/Fedora/CentOS 系统上的标准策略,它在增强安全性和减少对现有应用程序影响之间达到了一个很好地平衡。
CentOS7 系统中,Targeted Policy 源文件可以在 /etc/selinux/targeted/src/policy/
目录下找到。
Targeted Policy 中使用了无限制的域类型 unconfined_t
,并移除了 strict 策略中的 sysadmin_t
和 user_t
域类型,这也意味着基本的角色结构被移除,所有的用户都以角色 system_r
来运行,几乎所有用户运行的程序都以 unconfined_t
域类型执行。不过,无限制域和限制域都需要接受可执行和可写的内存检查。默认情况下,运行在无限制域下的主体不能分配可写和可执行的内存,这个机制降低了系统遭受缓冲区溢出攻击的风险。这些内存检查可以通过设置SELinux Boolean 变量来关掉,下文详述。
5.2 限制进程
几乎所有的网络服务进程都在限制下运行;多数以 root
身份运行的系统进程(比如 passwd
进程)都是受限的。当进程受限时,它只能在自己被限制的域内运行,只能操作该域内的资源(文件、服务等),对其他域的资源则无权操作。比如 Web 服务进程 httpd
只能运行在 httpd_t
域内。如果一个受限制的进程被黑客攻击并控制,根据 SELinux 策略的配置,该黑客仅仅能访问这个受限制的域,因此攻击所带来的危害也比传统的 Linux 小很多。
以下通过一个具体的例子来演示 SELinux 如何将进程限制在自己的域内运行,本例以Apache服务器的进程 httpd
为例,介绍 SELinux 如何阻止 httpd
进程去访问由其他域管理的文件类型的。
运行
sestatus
命令来确认 CentOS7 中 SELinux 试运行的,它运行在enforcing
模式下(SELinux 有3种运行模式,下文详述),且采用了 Targeted Policy:12345678910➜ sestatusSELinux status: enabledSELinuxfs mount: /sys/fs/selinuxSELinux root directory: /etc/selinuxLoaded policy name: targetedCurrent mode: enforcingMode from config file: enforcingPolicy MLS status: enabledPolicy deny_unknown status: allowedMax kernel policy version: 28用
root
权限在httpd
的工作目录下创建一个新的文件info.php
(显示 PHPINFO 的内容):1234➜ cat /var/www/html/info.php<?phpecho phpinfo();?>查看该文件的 SELinux 上下文信息:
12➜ ls -Z /var/www/html/info.php-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/info.php
NOTE:
至此,可以看出,默认情况下,Linux用户是非限制的,因此刚创建的info.php
文件的 SELinux 上下文中的用户标记为unconfined_u
。然而RBAC访问控制机制是作用于进程的,不是用于文件,并且,角色对文件来说也没什么太大意义,因此上述结果中的object_u
的角色也仅仅是一个用与文件的通用角色。在/proc/
目录下,与进程相关的文件可以采用system_r
角色。另外,结果中的httpd_sys_context_t
类型允许运行在httpd_t
域 中的httpd
进程访问该文件。
- 访问
info.php
文件,如下图所示:
可知该文件默认是可以被访问到的。
- 使用
chcon
命令对该文件的类型重新标识。下面,以root
用户身份运行如下命令将上述info.php
文件的类型改为可由运行在samba_share_t
域内的 Samba 进程访问的文件:123➜ chcon -t samba_share_t info.php➜ ls -Z info.php-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 info.php
可以看到该文件的类型已被改为 samba_share_t
,需要注意的是,这种方法的修改是临时的,若要永久修改文件的类型,需要用 semanage
命令,下文详述。
- 再次访问该
info.php
文件,就会发现被禁止访问了:
通过上述几个步骤的演示可知,虽然 Linux 系统基本的 DAC 机制允许 httpd
进程访问 info.php
文件,然而 SELinux 实现的 MAC机制却进制该访问操作。同时, SELinux 还对这些操作详情记录到日志中,以方便系统管理员事后审计与分析。SELinux 审计日志可查看 /var/log/audit/audit.log
文件:
当然,由于该操作涉及 httpd
服务进程,Apache 也有自己的日志文件,因此,也可以查看 Apache 服务器的错误日志文件 /var/log/httpd/error_log
:
5.3 非限制进程
非限制进程运行在非限制域中。比如,init
进程运行在非限制的 initrc_t
域 中,非限制的 Kernel 进程运行在 kernel_t
域中,非限制的用户运行在 unconfined_t
域中。对于非限制的进程, SELinux 的策略规则仍然适用,然而有关允许进程运行在非限制域的规则几乎允许所有的访问。此时,相当于 SELinux 不起作用,SELinux 架起来的防护只相当于“退化”到传统的 DAC机制。如果一个非限制进程被黑客控制,那么 SELinux 将无法阻止黑客进一步活动(当然 DAC 规则仍然适用, SELinux 只是在 DAC 层次上附加了一层更高强度的防护,而不是替代 DAC 机制)。
下面将给出一个具体的例子来演示 Apache HTTP 服务器的 httpd
进程在非限制条件下运行时,是如何访问本应由 Samba 服务器访问的数据的。(下面的例子需要安装 SELinux 相关的 setroubleshoot-server
、audit
等工具包,同上,SELinux 也需要运行在 enforcing
模式下)。
通过
sestatus
命令检查 SELinux 的运行状态:12345678910➜ sestatusSELinux status: enabledSELinuxfs mount: /sys/fs/selinuxSELinux root directory: /etc/selinuxLoaded policy name: targetedCurrent mode: enforcingMode from config file: enforcingPolicy MLS status: enabledPolicy deny_unknown status: allowedMax kernel policy version: 28确保上述的
info.php
文件 SELinux 上下文中的类型仍然是samba_share_t
:12➜ ls -Z-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 info.phphttpd
进程原来运行在受限制 的httpd_t
域 内,其进程启动文件/usr/sbin/httpd
的文件类型为httpd_exec_t
:12345678910➜ ls -Z /usr/sbin/httpd-rwxr-xr-x. root root system_u:object_r:httpd_exec_t:s0 /usr/sbin/httpd➜➜ ps -eZ | grep httpdsystem_u:unconfined_r:httpd_t:s0 23284 ? 00:00:00 httpdsystem_u:unconfined_r:httpd_t:s0 23286 ? 00:00:00 httpdsystem_u:unconfined_r:httpd_t:s0 23287 ? 00:00:00 httpdsystem_u:unconfined_r:httpd_t:s0 23288 ? 00:00:00 httpdsystem_u:unconfined_r:httpd_t:s0 23289 ? 00:00:00 httpdsystem_u:unconfined_r:httpd_t:s0 23290 ? 00:00:00 httpd在将
httpd
进程从 限制 改为 非限制 之前,需要先终止该进程:1➜ systemctl stop httpd.service以
root
用户身份运行以下命令来改变httpd
进程启动命令文件的 类型,以确保其启动之后不运行在原来的httpd_t
域 内(将/usr/sbin/httpd
的 类型 改为unconfined_exec_t
,启动后进程将运行在unconfind_t
非限制域 内):123456789101112➜ chcon -t unconfined_exec_t /usr/sbin/httpd➜ ls -Z /usr/sbin/httpd-rwxr-xr-x. root root system_u:object_r:unconfined_exec_t:s0 /usr/sbin/httpd➜➜ systemctl start httpd.service➜ ps -eZ | grep httpdsystem_u:unconfined_r:unconfined_t:s0 23284 ? 00:00:00 httpdsystem_u:unconfined_r:unconfined_t:s0 23286 ? 00:00:00 httpdsystem_u:unconfined_r:unconfined_t:s0 23287 ? 00:00:00 httpdsystem_u:unconfined_r:unconfined_t:s0 23288 ? 00:00:00 httpdsystem_u:unconfined_r:unconfined_t:s0 23289 ? 00:00:00 httpdsystem_u:unconfined_r:unconfined_t:s0 23290 ? 00:00:00 httpd此时,用运行在 非限制域 内的
httpd
进程访问本来只能由 Samba 进程访问的、类型为samba_share_t
的info.php
文件:
该结果显示,虽然httpd
进程原来没有访问标记为samba_share_t
类型的文件的权限,然而由于httpd
现在运行在非限制域unconfined_t
中,所以 SELinux 的防护策略没起作用,相当于只有 Linux 系统的 DAC 机制起作用。- 测试结束后,可以用
restorecon
命令来恢复文件的默认类型,下面依次恢复上述测试中的两个文件的默认类型,并重新启动相关进程:12345678910111213141516➜ restorecon -v /var/www/html/info.phprestorecon reset /var/www/html/info.php context unconfined_u:object_r:samba_share_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0➜ ls -Z /var/www/html/info.php-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/info.php➜➜ systemctl stop httpd.service➜ restorecon -v /usr/sbin/httpdrestorecon reset /usr/sbin/httpd context system_u:object_r:unconfined_exec_t:s0->system_u:object_r:httpd_exec_t:s0➜ systemctl start httpd.service➜ ps -eZ | grep httpdsystem_u:system_r:httpd_t:s0 24479 ? 00:00:00 httpdsystem_u:system_r:httpd_t:s0 24481 ? 00:00:00 httpdsystem_u:system_r:httpd_t:s0 24482 ? 00:00:00 httpdsystem_u:system_r:httpd_t:s0 24483 ? 00:00:00 httpdsystem_u:system_r:httpd_t:s0 24484 ? 00:00:00 httpdsystem_u:system_r:httpd_t:s0 24485 ? 00:00:00 httpd
上述步骤演示了 SELinux 如果通过限制进程的运行来保证 Linux 系统安全的,也演示了如果将重要进程改为非限制进程的安全隐患,因此,将一个进程的运行状态由限制改为非限制的时候,应当十分慎重。
3.4.4 限制和非限制用户
前文介绍过,每个 Linux 系统用户在 SELinux 中都被映射为一个 SELinux User,这使得 Linux 用户能够继承在 SELinux 实现的 SELinux User 访问控制。用 semanage login -l
查看两种用户间的映射情况:
CentOS7 中,Linux 用户被默认映射到 SELinux 的 __default__
login 中,从而映射为 unconfined_u
类型。下面通过一个具体的在 CentOS7 中添加新用户的例子,来掩饰 SELinux 是如何映射 Linux 系统用户的。
以
root
用户身份,运行useradd
命令新增用户jiayu
,并用passwd
命令给新用户设置密码:12➜ useradd jiayu➜ passwd jiayu用
su jiayu
命令切换到用户jiayu
登录 Shell,并用id -Z
命令查看该用户的 SELinux 上下文:123➜ su jiayu[jiayu@localhost ~]$ id -Zunconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
由上面步骤可以看到,当 Linux 添加一个新用户时, SELinux 默认将该用户映射为 unconfined_u
类型,角色 为 unconfined_r
,域 为 unconfined_t
。
限制和非限制的用户都需要接受可执行和可写的内存检查,并接受 MCS(Multi-Category Security) 与 MLS(Multi-Level Security)机制的约束。如果一个非限制用户执行了一个从 unconfined_t
域向一个允许的域转变的应用程序,非限制用户仍要接受那个转变到的域的限制。这个机制就保证了即使一个用户是非限制的,这个应用也是受限的,因此,软件的漏洞引起的风险仍能得到一定程度的控制。
3.4.5 策略目录介绍
SELinux 系统上安装的每个策略在 /etc/selinux/
目录下都有他们自己的目录,子目录的名字对应于策略的名字(如本小节介绍的 Targeted Policy
),在 SELinux 配置文件中就要使用这些子目录名字,高速内核在启动时载入什么策略。看下 CentOS7 上 /etc/selinux/
目录中内容:
上面结果显示,CentOS7 系统默认只安装了一个策略:targeted 。注意目录和策略子目录的类型都是 selinux_config_t
。
semodule
和 semanage
命令管理策略的诸多方面,前者管理可载入策略模块的安装、更新和删除,它对可载入策略包起作用,包括一个可载入策略模块和文件上下文消息;后者管理添加、修改和删除用户、角色文件上下文、MLS/MCS转换、端口标记和接口标记。
每个策略子目录包括的文件,以及文件如何标记必须遵守一个规范,这个规范被许多系统实用程序使用,帮助管理策略。通常,任何设计优良的策略源树都将正确安装策略文件,下面是 targeted
策略目录的列表输出,它就是一个典型:
6. SELinux 配置文件及启用/禁用
6.1 配置文件
SELinux 的主配置文件是 /etc/selinux/config
文件,它控制系统下一次启动过程中载入哪个策略。以及 SELinux 以什么样的模式运行。下面显示了一个 config
文件的内容:
该配置文件主要控制两个方面的设置:SELinux 的 运行模式 和 活动策略。
SELinux 模式(由上面
SELINUX=enforcing
一行确定):可以被设置为enforcing
/permissive
/disabled
共3种。enforcing
模式,在该模式下,SELinux 策略背完政治性,这是 SELinux 主要工作模式要使 SELinux 发挥增强系统安全的作用,必须开启此模式;permissive
模式,该模式下,SELinux 的策略规则不会被强制执行,相反,只是审核并记录遭受拒绝的消息,除此之外,SELinux 对系统的安全性没有影响,此模式在调试 SELinux 策略时很有帮助;disabled
模式,内核中的 SELinux 机制完全关闭,只有系统启动时策略载入前系统才会处于disabled
模式,该模式和permissive
模式有所不同,permissive
模式有 SELinux 内合特征操作,但不会拒绝任何访问,只是进行审核、记录;在disabled
模式下, SELinux 将不会有任何动作,只有在不希望使用 SELinux 时才使用该模式。NOTE:
在enforcing
模式和permissive
模式或者disabled
模式之间切换要小心,当返回enforcing
模式时,通常会导致文件标记不一致。SELinux 配置文件中的模式设置由init
进程使用,在它载入初始策略前配置 SELinux 使用。
SELinux 活动策略:SELinux 配置文件中的
SELINUXTYPE
配置项告诉init
进程在系统启动过程中载入哪个 SELinux 策略,这里设置的字符串必须匹配用来存储二进制策略版本的目录名,例如,我们使用targeted
策略为例,因此设置SELINUXTYPE=targeted
。
6.2 启用/禁用 SELinux
启用/禁用 SELinux步骤很简单,只需修改其配置文件,然后重启系统即可。
启用 SELinux
编辑配置文件
/etc/selinux/config
。根据前面对配置文件的介绍,编辑确定 SELinux 的运行模式(enforcing)和活动策略(targeted):1234567891011# 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重启系统:
1shutdown -r now
禁用 SELinux
编辑配置文件
/etc/selinux/config
。根据前面对配置文件的介绍,编辑 SELinux 的运行模式(disabled):1234567891011# 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=disabled# 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重启系统:
1shutdown -r now
7. SELinux 布尔值(Booleans)
SELinux 中的布尔值允许 SELinux 在运行状态下动态调整部分策略,而无需重新加载 SELinux 或 重新编译 SELinux 策略,比如 允许某些服务访问 NFS 卷。
7.1 查看 SELinux 布尔值
以 root
用户身份,运行 semanage boolean -l
命令,即可查看包括 关闭(off) 和 打开(on) 状态的所有布尔变量,下面是部分布尔值列表:
上面三列内容的意义:
- SELinux 布尔值 列出了 SELinux 布尔值的名称;
- 状态 默认 一对数据列出了对应布尔值当前的开关状态与默认状态;
- 描述 列出了布尔值的用途。
比如第一行的 ftp_home_dir
当前状态和默认状态都是 关(off) ,这条策略组织 FTP 服务的守护进程(比如 vsftpd
)读/写 用户主目录里的文件。
getsebool -a
命令会简要列出 SELinux 布尔值及其 当前状态(默认安字典序) ,而无其他信息,下面是部分结果:
而运行 getsebool [boolean-name]
命令则会列出指定布尔值的当前状态:
上面例子中,还可以用 空格 隔开多个布尔值名称,用以一次查看多个布尔值变量的状态:
7.2 配置布尔值
以 root
用户身份运行 setsebool [boolean_name] [on|off]
命令就可以将指定的布尔值状态修改成 关闭 或 打开。下面用一个实例演示如何用此命令调整布尔值 httpd_can_network_connect_db
的状态。
布尔值
httpd_can_network_connect_db
用以 允许/阻止 HTTP 服务器访问数据库服务,默认状态为off
:12➜ getsebool httpd_can_network_connect_dbhttpd_can_network_connect_db --> off下面的命令可以 临时允许 HTTP 服务器中的脚本或模块访问数据库服务器:
1234➜ setsebool httpd_can_network_connect_db on➜➜ getsebool httpd_can_network_connect_dbhttpd_can_network_connect_db --> on
即可发现状态修改成功。
- 需要注意的是上述修改知识 临时 的,重启系统即会失效,若要 永久 修改某个布尔值的状态,需要对
setsebool
命令加-P
参数:1➜ setsebool -P httpd_can_network_connect_db on
8. SELinux 上下文修改与恢复
在前文『3.4.2 限制进程』与『3.4.3 非限制进程』两个小节的例子中,曾经使用过 chcon
命令来修改文件的类型,用 restorecon
命令来恢复文件的类型,本小节再多介绍一下其用法。
8.1 临时修改上下文
chcon
命令可以修改文件的 SELinux 上下文,但其功能不止能修改前文例子中的类型,类型只是 SELinux 上下文的 4 个主要元素(user:role:type:level
)之一,而该命令可以修改任何一个元素。先看其 Usage:
有两个要点需要注意:
- 根据
chcon
命令的 Usage ,前文只用-t
参数修改了指定文件的 类型,而还可以用-u
参数修改文件的 SELinux user,用-r
参数修改指定文件的 角色,用-l
参数修改文件的 level。用法雷同,此处不详述; - 除了能修改 文件 的上下文,该命令还能修改 目录 的上下文信息,参数
-R
可以递归地修改目录下所有文件、子目录及子目录里的文件的上下文信息; chcon
命令对 文件/目录 上下文的修改是 临时 性的,重启系统即会失效,若要 永久 修改上下文信息,需要用semanage
命令,下文详述。
restorecon
命令用法单一,功能也单一,仅仅是恢复 文件/目录 的默认上下文信息。
8.2 永久修改上下文
如前文所述,semanage
命令可以 永久性 修改 文件/目录 的上下文信息。当 SELinux 使用 Targeted Policy 时,该命令修改的文件的上下文先信息存储在 /etc/selinux/targeted/contexts/files/
目录:
file_contexts
文件存放的是大部分文件的默认上下文信息,包括semanage fcontext
命令更新的文件上下文信息;file_contexts.local
文件存放的是file_contexts
文件中不存在的、新增文件/目录的上下文信息。
有两个工具可以访问上述两个文件:setfiles
和 restorecon
。前者在文件系统重新加载的时候重新标记文件上下文;后者在恢复指定文件的上下文信息的时候读取该文件的默认上下文。由此可知,semanage fcontext
命令修改的文件上下文是永久性的,无论文件系统是否重新加载。至于某个 Linux 系统用户能够修改指定文件的上下文信息,则由 SELinux 的策略规则控制。
semanage
命令的用法:
可以看到 semanage
命令下有个 子命令 fcontext
,可以管理文件的上下文,其 Usage
为:
用 semanage fcontext
命令永久性修改 文件/目录 的上下文,需要两个步骤:
设定指定 文件/目录 的默认上下文(注意文件/目录的路径要用完整路径):
1semanage fcontext -a [options] [file|dir]用
restorecon
命令还原该文件/目录的上下文:1restorecon -v [file|dir]
永久修改文件/目录上下文
下面实例演示一下如何永久性修改一个文件/目录的上下文信息。
- 以
root
用户身份在/etc/
目录下新建一个文件file
(按照 SELinux 策略规则,/etc/
目录下的新建文件默认类型为etc_t
):123/etc ➜ touch file1/etc ➜ ls -Z file1-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 file1
NOTE:
此处的file1
,也可是新建一个目录,查看指定目录的 SELinux 上下文信息可用命令:ls -dZ [dir]
- 以
root
用户身份运行以下命令将file1
的 类型 修改为samba_share_t
:123➜ semanage fcontext -a -t samba_share_t /etc/file1➜ ls -Z /etc/file1-rw-r--r--. root root unconfined_u:object_r:etc_t:s0 /etc/file1
上述 semanage fcontext
命令往 /etc/selinux/targeted/contexts/files/file_contexts. local
文件中新增了一条规则:
NOTE:
选项-a
代表要 新增 一条规则到前文所述的file_contexts.local
文件;选项-t
代表要修改的上下文元素为 类型。可以看到semanage fcontext
命令执行后,/etc/file1
文件新的上下文并没有立即生效。
- 用
restorecon
命令恢复/etc/file1
的上下文。因为前面的操作为该文件在file_contexts.local
中新增了一条记录,restorecon
命令会从file_contexts.local
中读取这一条规则为/etc/file1
恢复上下文,进而将/etc/file1
的类型改为samba_share_t
:12345➜ restorecon -v /etc/file1restorecon reset /etc/file1 context unconfined_u:object_r:etc_t:s0->unconfined_u:object_r:samba_share_t:s0➜➜ ls -Z /etc/file1-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 /etc/file1
一次性永久修改目录和其中文件的上下文
semanage fcontext
命令还支持通过匹配目录下所有文件/目录的正则表达式,来批量永久修改指定目录及其下属所有文件/目录的 SELinux 上下文。下面实例演示如何新建一个目录,将它以及它内部所有的文件/子目录类型修改为可供 Apache HTTP 服务器访问的 httpd_sys_content_t
(如果需要将 HTTP 服务器主目录改到别处,此例会非常有用)。
以
root
用户身份新建一个目录/web/
,并在其中新建三个文件file1
/file2
/file3
,该目录和其中的文件默认 类型 将会是default_t
:12345678➜ mkdir /web➜ touch /web/file{1,2,3}➜ ls -dZ /webdrwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /web➜ ls -Z /web-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file1-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file2-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file3以
root
用户身份用semanage fcontext
命令将/web
目录及其中的 3 个文件的 类型 改为httpd_sys_content_t
(同前面的例子,不会马上生效):1234567➜ semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"➜ ls -dZ /webdrwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /web➜ ls -Z /web-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file1-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file2-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file3
同前面的例子,semanage fcontext
命令往 /etc/selinux/targeted/contexts/files/file_contexts. local
文件中新增了一条规则:
NOTE:
上述例子中semanage fcontext
命令里的正则表达式"/web(/.*)?"
表示/web/
目录自己机器中的所有 文件/子目录。
- 同样,用
restorecon
命令恢复/web
目录及其中所有文件/子目录的上下文:12345➜ restorecon -Rv /webrestorecon reset /web context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0restorecon reset /web/file1 context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0restorecon reset /web/file2 context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0restorecon reset /web/file3 context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:httpd_sys_content_t:s0
NOTE:
按照 SELinux 的默认策略,目录中新增文件的 SELinux 上下文将继承自目录的 SELinux 上下文,所以,经过上面的操作,如果/web/
目录下再有新增文件/子目录,它们的 SELinux 上下文的 类型 将会是httpd_sys_content_t
。
删除新增 SELinux 策略规则
通过 semanage fcontext -a
命令新增的 SELinux 上下文规则,可以通过 semanage fcontext -d [file|dir]
命令来删除(可以参考semanage fcontext
的 Usage
)。通常分两个步骤,先删除,后 restorecon
。如果删除时遇到正则表达式(比如上面的 /web(/.*)?
),一定要用半角双引号将正则括起来,例如:
选项 -d
后面的 [file|dir]
是 semanage fcontext -a [options] [file|dir]
命令添加上下文规则是指定的 文件/目录 ,也是 /etc/selinux/targeted/contexts/files/file_contexts. local
文件中的 第一列,如下面的 /etc/file
和 /web(/.*)?
:
比如我们要删除上面对 /web
目录及其里面文件/子目录的新增上下文类型,只需按照下面的步骤来操作:
删除记录(不会立即生效):
12345678910➜ semanage fcontext -d "/web(/.*)?"➜ cat /etc/selinux/targeted/contexts/files/file_contexts.local# This file is auto-generated by libsemanage# Do not edit directly.➜ ls -dZ /webdrwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /web➜ ls -Z /web-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 file1-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 file2-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 file3恢复默认上下文:
1234567891011➜ restorecon -Rv /webrestorecon reset /web context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:default_t:s0restorecon reset /web/file1 context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:default_t:s0restorecon reset /web/file2 context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:default_t:s0restorecon reset /web/file3 context unconfined_u:object_r:httpd_sys_content_t:s0->unconfined_u:object_r:default_t:s0➜ ls -dZ /webdrwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /web➜ ls -Z /web-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file1-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file2-rw-r--r--. root root unconfined_u:object_r:default_t:s0 file3
可以看到 /web
目录及其下属所有文件的 SELinux 上下文类型都恢复到初始的default_t
了。
9. SELinux 上下文保持
本小节解释 文件/目录 在 拷贝/移动/归档打包 过程中其 SELinux 上下文发生的变化,以及如何在 拷贝 和 归档打包 过程中保留原 SELinux 上下文。
9.1 拷贝 文件/目录
默认情况下,将一个文件/目录 拷贝到另一个地方(假设目的目录的 SELinux上下文不同于文件原来的上下文),最后在新位置的文件 SELinux 上下文将继承目的目录的上下文,示例如下:
由此可知,原来在 /root
目录下 SELinux 上下文类型为 admin_home_t
的 test.txt
文件,用 cp
命令直接拷贝到 /etc/
目录,其 SELinux 上下文 类型 就会变成 /etc/
目录中默认的类型 etc_t
(假设 /etc/test.txt
文件原来不存在)。
上面的例子中,如果 /etc/test.txt
文件原本就存在,那么直接用 cp
命令将执行 覆盖拷贝 ,但新的 /etc/test.txt
SELinux 上下文将 不变(既不继承 /etc/
默认的上下文类型,也不会被原来 /root/test.txt
的 SELinux 上下文类型所覆盖)。
保留原上下文
若要拷贝过程中,保留源文件的 SELinux 上下文类型,则需要对 cp
命令加上选项 --preserve=context
,示例如下:
由此例可知,对 cp
命令加上选项 --preserve=context
后,将文件 test.txt
从 /root
目录拷贝到 /etc/
目录,其 SELinux 上下文 类型 依然是 admin_home_t
。
拷贝过程中更改上下文
还可以在拷贝文件过程中更改 SELinux 上下文,新生成的文件上下文将会既不同于源文件的上下文,也不同于目的目录的默认上下文。只要对 cp
命令加上选项 --context=[user:role:type:level]
即可,示例如下 :
由此例可知,在拷贝过程中对 cp
命令加上选项 --context=system_u:object_r:samba_share_t:s0
后,新生成的 /etc/test.txt
文件的 SELinux 上下文就变成了 system_u:object_r:samba_share_t:s0
。
9.2 移动 文件/目录
Linux 中的 mv
命令来移动 文件/目录,会将 源文件/源目录 的 SELinux 上下文也一并附带移动,到目的地址新生成的 文件/目录 将保持与 源文件/源目录 相同的 SELinux 上下文。所以,在启用 SELinux 的 Linux 系统中,移动操作需要额外注意 SELinux 上下文信息。此处无示例演示。
9.3 使用 tar 归档打包 文件/目录
默认情况下,使用 tar
命令归档打包 文件/目录 时,是不附带 SELinux 上下文信息的,将一个 tar 包解开到新目录,其中的文件将会继承新目录的 SELinux 上下文,示例如下:
上面的例子可知,在 /var/www/html
目录新建的 3 个 SELinux 上下文类型为 httpd_sys_content_t
的文件,进过 tar
命令直接打包,然后拷贝到 /root
目录再解压,其中的 3 根文件 SELinux 上下文 类型 却变成了 admin_home_t
。
有没有办法在打包归档过程中保留原始文件的 SELinux 上下文信息?
其实,tar
命令提供了一个选项 --selinux
,使用 tar --selinux -cf test. tar [files]
的形式,即可保留源文件的 SELinux 上下文信息,此处不做演示。
10. 检查默认上下文
用 matchpathcon
工具可以检查指定的 文件/目录 的 SELinux 上下文是否“正确”,该工具会索引系统默认的 SELinux 策略,并以此检查指定的 文件/目录 的 SELinux 上下文是否与默认策略吻合。下面示例演示如何使用该工具。
在上面例子中,第 2 条命令用 chcon
将 /var/www/html/file1
的 SELinux 上下文 类型 改为 samba_share_t
,然后第 4 条命令用 matchpathcon
检测到该文件的 SELinux 上下文应为 system_u:object_r:httpd_sys_content_t:s0
,随后用 restorecon
命令就会将该文件的 SELinux 上下文“修正”。
11. 总结
本系列 2 篇文档从最基本的安全模型开始,把 Linux 系统中实现的权限管理与访问控制从UGO+RWX
机制到 ACL 机制到最后的 SELinux,详细介绍一遍。
由上面的内容可知,这些 Linux 系统中实现的安全机制与策略,是依次增强的,对权限和访问的管理、控制粒度是依次减小的,所以能得到更灵活也更安全的配置,当然,也更复杂繁琐。
机制本身的安全性毋庸置疑,只是如果在使用相关工具对这些安全机制进行安全配置时,如果掌握不好配置方法与注意事项,那么配置出来的系统可能会有安全隐患,例如不恰当地应用 setuid
位。
最后的 SELinux 部分,其实只介绍了其安全模型设计原理、SELinux 中的元素和工作原理、基础的管理与配置,这些都是使用 SELinux 的基础知识,掌握这些基础知识,才能对 SELinux 进行基础地使用。而 SELinux 的一些高级用法,比如自定义编写、编译策略规则,本文档并未介绍。