搜索

使用 SELinux

download PDF
Red Hat Enterprise Linux 9

防止用户和进程使用增强安全的 Linux (SELinux)与文件和设备执行未授权的交互

Red Hat Customer Content Services

摘要

通过配置 SELinux,您可以增强系统的安全性。SELinux 是一种强制访问控制(MAC)的实现,它提供额外的安全层。SELinux 策略定义了用户和进程如何与系统上的文件进行交互。您可以通过将用户映射到特定的 SELinux 受限用户来控制哪些用户可以执行哪些操作。

对红帽文档提供反馈

我们感谢您对我们文档的反馈。让我们了解如何改进它。

通过 Jira 提交反馈(需要帐户)

  1. 登录到 Jira 网站。
  2. 在顶部导航栏中点 Create
  3. Summary 字段中输入描述性标题。
  4. Description 字段中输入您的改进建议。包括文档相关部分的链接。
  5. 点对话框底部的 Create

第 1 章 SELinux 入门

SELinux(Security Enhanced Linux)提供了一个额外的系统安全层。SELinux 从根本上解决以下问题:May <subject> do <action> to <object>?, 例如:Web 服务器是否可以访问用户主目录中的文件?

1.1. SELinux 简介

系统管理员一般无法通过基于用户、组群和其它权限(称为 Discretionary Access Control,DAC)的标准访问策略生成全面、精细的安全策略。例如,限制特定应用程序只能查看日志文件,而同时允许其他应用程序在日志文件中添加新数据。

Security Enhanced Linux(SELinux)实现强制访问控制(MAC)。每个进程和系统资源都有一个特殊的安全性标签,称为 SELinux 上下文(context)。SELinux 上下文有时被称为 SELinux 标签,它是一个提取系统级别细节并专注于实体的安全属性的标识符。这不仅提供了在 SELinux 策略中引用对象的一个一致方法,而且消除了在其他身份识别系统中可能存在的模糊性。例如,某个文件可以在使用绑定挂载的系统中有多个有效的路径名称。

SELinux 策略在一系列规则中使用这些上下文,它们定义进程如何相互交互以及与各种系统资源进行交互。默认情况下,策略不允许任何交互,除非规则明确授予了相应的权限。

注意

请记住,对 SELinux 策略规则的检查是在 DAC 规则后进行的。如果 DAC 规则已拒绝了访问,则不会使用 SELinux 策略规则。这意味着,如果传统的 DAC 规则已阻止了访问,则不会在 SELinux 中记录拒绝信息。

SELinux 上下文包括以下字段: user(用户)、role(角色)、type(类型)和 security level(安全级别)。在 SELinux 策略中,SELinux 类型信息可能是最重要的。这是因为,最常用的、用于定义允许在进程和系统资源间进行的交互的策略规则会使用 SELinux 类型而不是 SELinux 的完整上下文。SELinux 类型以 _t 结尾。例如,Web 服务器的类型名称为 httpd_t。通常位于 /var/www/html/ 中的文件和目录的类型上下文是 httpd_sys_content_t。通常位于 /tmp and /var/tmp/ 中的文件和目录的类型上下文是 tmp_t。Web 服务器端口的类型上下文是 http_port_t

有一个策略规则允许 Apache(作为 httpd_t运行的 Web 服务器进程)访问通常位于 /var/www/html/ 和其他 Web 服务器目录中上下文的文件和目录(httpd_sys_content_t)。策略中没有允许规则适用于通常位于 /tmp/var/tmp/ 中的文件,因此不允许访问。因此,当使用 SELinux 时,即使 Apache 被破坏,一个恶意的脚本可以访问它,也无法访问 /tmp 目录。

图 1.1. 通过 SELinux 以安全的方式运行 Apache 和 MariaDB 的示例。

SELinux_Apache_MariaDB_example

如上图所示,SELinux 允许作为 httpd_t 运行 Apache 进程访问 /var/www/html/ 目录,并且拒绝同一进程访问 /data/mysql/ 目录,因为 httpd_tmysqld_db_t 类型上下文没有允许规则。另一方面,作为 mysqld_t 运行的 MariaDB 进程可以访问 /data/mysql/ 目录,SELinux 也会正确地拒绝使用 mysqld_t 类型的进程来访问标记为 httpd_sys_content_t/var/www/html/ 目录。

其他资源

  • selinux(8) 手册页和 apropos selinux 命令列出的 man page。
  • 在安装了 selinux-policy-doc 软件包后,man -k _selinux 命令会列出 man page。
  • The SELinux Coloring Book 可帮助您更好地了解 SELinux 基本概念。。
  • SELinux Wiki FAQ

1.2. 运行 SELinux 的好处

SELinux 提供以下优点:

  • 所有进程和文件都被标记。SELinux 策略规则定义了进程如何与文件交互,以及进程如何相互交互。只有存在明确允许的 SELinux 策略规则时,才能允许访问。
  • SELinux 提供精细的访问控制。传统的 UNIX 通过用户的授权、基于 Linux 的用户和组进行控制。而 SELinux 的访问控制基于所有可用信息,如 SELinux 用户、角色、类型以及可选的安全级别。
  • SELinux 策略由系统管理员进行定义,并在系统范围内强制执行。
  • SELinux 可以缓解权限升级攻击。进程在域中运行,因此是相互分离的。SELinux 策略规则定义了如何处理访问文件和其它进程。如果某个进程被破坏,攻击者只能访问该进程的正常功能,而且只能访问已被配置为可以被该进程访问的文件。例如:如果 Apache HTTP 服务器被破坏,攻击者无法使用该进程读取用户主目录中的文件,除非添加或者配置了特定的 SELinux 策略规则允许这类访问。
  • SELinux 可以强制实施数据保密性和完整性,并可以防止进程不受不受信任的输入的影响。

SELinux 旨在增强现有的安全解决方案,而不是替换 antivirus 软件、安全密码、防火墙或其他安全系统。即使运行 SELinux,仍需要遵循好的安全实践,如保持软件更新、使用安全的密码、使用防火墙。

1.3. SELinux 示例

以下示例演示了 SELinux 如何提高安全性:

  • 默认操作为 deny(拒绝)。如果 SELinux 策略规则不存在允许访问(如允许进程打开一个文件),则拒绝访问。
  • SELinux 可以限制 Linux 用户。SELinux 策略中包括很多受限制的 SELinux 用户。可将 Linux 用户映射到受限制的 SELinux 用户,以便利用其使用的安全规则和机制。例如,将 Linux 用户映射到 SELinux user_u 用户,这会导致 Linux 用户无法运行,除非有其他配置的用户 ID(setuid)应用程序,如 sudosu
  • 增加进程和数据的分离。SELinux 域(domain)的概念允许定义哪些进程可以访问某些文件和目录。例如:在运行 SELinux 时,除非有其他配置,攻击者将无法侵入 Samba 服务器,然后使用 Samba 服务器作为攻击向量读取和写入其它进程使用的文件(如 MariaDB 数据库)。
  • SELinux 可帮助缓解配置错误带来的破坏。在区传输(zone transfer)过程中,不同的 DNS 服务器通常会在彼此间复制信息。攻击者可以利用区传输来更新 DNS 服务器使其包括错误的信息。当在 Red Hat Enterprise Linux 中使用 BIND(Berkeley Internet Name Domain)作为 DNS 服务器运行时,即使管理员没有限制哪些服务器可执行区传输,默认的 SELinux 策略也会阻止区文件 [1] 通过 BIND named 守护进程本身或其它进程,使用区传输。
  • 如果没有 SELinux,攻击者可以利用漏洞在 Apache Web 服务器上路径遍历,并使用特殊元素(如 ../)访问存储在文件系统中的文件和目录。如果攻击者尝试对使用了强制模式运行 SELinux 的服务器进行攻击,SELinux 会拒绝对 httpd 进程不能访问的文件的访问。虽然 SELinux 无法完全阻止这型的攻击,但它可以有效地缓解它。
  • 使用强制(enforcing)模式的 SELinux 可以成功防止利用 kernel NULL pointer dereference operators on non-SMAP platforms (CVE-2019-9213) 安全漏洞进行攻击。攻击者可以利用 mmap 功能中的一个漏洞(不检查 null 页面的映射)将任意代码放在本页中。
  • deny_ptrace SELinux boolean 和使用 enforcing 模式的 SELinux 的系统可以防止利用 PTRACE_TRACEME 安全漏洞 (CVE-2019-13272) 进行的攻击。这种配置可以防止攻击者获得 root 特权。
  • nfs_export_all_rwnfs_export_all_ro SELinux 布尔值提供了一个易于使用的工具,以防止错误配置网络文件系统 (NFS),如意外地共享了 /home 目录。

其他资源



[1] 包括 DNS 信息(如主机名到 IP 地址映射)的文本文件。

1.4. SELinux 构架和软件包

SELinux 是一个内置在 Linux 内核中的 Linux 安全模块(LSM)。内核中的 SELinux 子系统由安全策略驱动,该策略由管理员控制并在引导时载入。系统中所有与安全性相关的、内核级别的访问操作都会被 SELinux 截取,并在加载的安全策略上下文中检查。如果载入的策略允许操作,它将继续进行。否则,操作会被阻断,进程会收到一个错误。

SELinux 决策(如允许或禁止访问)会被缓存。这个缓存被称为 Access Vector Cache(AVC)。通过使用这些缓存的决定,可以较少对 SELinux 策略规则的检查,这会提高性能。请记住,如果 DAC 规则已首先拒绝了访问,则 SELinux 策略规则无效。原始审计消息会记录到 /var/log/audit/audit.log,它们以 type=AVC 字符串开头。

在 RHEL 9 中,系统服务由 systemd 守护进程控制; systemd 启动和停止所有服务,用户和进程使用 systemctl 实用程序与 systemd 通信。systemd 守护进程可以参考 SELinux 策略,检查调用进程标签以及调用者试图管理的单元文件标签,然后询问 SELinux 是否允许调用者的访问。这个方法可控制对关键系统功能的访问控制,其中包括启动和停止系统服务。

systemd 守护进程也可以作为 SELinux 访问管理器使用。它检索运行 systemctl 或向 systemd 发送 D-Bus 消息的进程标签。然后守护进程会查找进程要配置的单元文件标签。最后,如果 SELinux 策略允许进程标签和单元文件标签之间的特定访问,systemd 就可以从内核中检索信息。这意味着,需要与特定服务交互的 systemd 进行交互的应用程序现在可以受 SELinux 限制。策略作者也可以使用这些精细的控制来限制管理员。

如果进程向另一个进程发送 D-Bus 消息,如果 SELinux 策略不允许这两个进程的 D-Bus 通信,则系统会打印 USER_AVC 拒绝消息,以及 D-Bus 通信超时。请注意,两个进程间的 D-Bus 通信会双向运行。

重要

为了避免不正确的 SELinux 标记以及后续问题,请确定使用 systemctl start 命令启动服务。

RHEL 9 提供以下用于 SELinux 的软件包:

  • 策略:selinux-policy-targeted, selinux-policy-mls
  • 工具: policycoreutils,policycoreutils-gui,libselinux-utils,policycoreutils-python-utils,setools-console,checkpolicy

1.5. SELinux 状态和模式

SELinux 可使用三种模式之一运行: enforcing(强制)、permissive(宽容)或 disabled(禁用)。

  • Enforcing 模式是默认操作模式,在 enforcing 模式下 SELinux 可正常运行,并在整个系统中强制实施载入的安全策略。
  • 在 permissive 模式中,系统会象 enforcing 模式一样加载安全策略,包括标记对象并在日志中记录访问拒绝条目,但它并不会拒绝任何操作。不建议在生产环境系统中使用 permissive 模式,但 permissive 模式对 SELinux 策略开发和调试很有帮助。
  • 强烈建议不要使用禁用(disabled)模式。它不仅会使系统避免强制使用 SELinux 策略,还会避免为任何持久对象(如文件)添加标签,这使得在以后启用 SELinux 非常困难。

使用 setenforce 实用程序在 enforcing 模式和 permissive 模式之间切换。使用 setenforce 所做的更改在重新引导后不会保留。要更改为 enforcing 模式,请以 Linux root 用户身份输入 setenforce 1 命令。要更改为 permissive 模式,请输入 setenforce 0 命令。使用 getenforce 实用程序查看当前的 SELinux 模式:

# getenforce
Enforcing
# setenforce 0
# getenforce
Permissive
# setenforce 1
# getenforce
Enforcing

在 Red Hat Enterprise Linux 中,您可以在系统处于 enforcing 模式时,将独立的域设置为 permissive 模式。例如,使 httpd_t 域为 permissive 模式:

# semanage permissive -a httpd_t

请注意,permissive 域是一个强大的工具,它可能会破坏您系统的安全性。红帽建议谨慎使用 permissive 域,如仅在调试特定情境时使用。

第 2 章 更改 SELinux 状态和模式

启用后,SELinux 可使用两种模式之一运行: enforcing 或 permissive。以下小节介绍了如何永久更改这些模式。

2.1. SELinux 状态和模式的更改

SELinux 状态和模式 中所述,SELinux 可以被启用或禁用。启用后,SELinux 有两个模式: enforcing 和 permissive。

使用 getenforcesestatus 命令检查 SELinux 的运行模式。getenforce 命令返回 EnforcingPermissiveDisabled

sestatus 命令返回 SELinux 状态以及正在使用的 SELinux 策略:

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
Memory protection checking:     actual (secure)
Max kernel policy version:      31
警告

当系统以 permissive 模式运行 SELinux 时,用户和进程可能会错误地标记各种文件系统对象。当禁用 SELinux 时创建的文件系统对象不会被标记。这会在将 SELinux 改为 enforcing 模式时导致问题,因为 SELinux 依赖于正确的文件系统对象标签。

为防止错误标记和未标记的文件造成问题,SELinux 在从 disabled 状态更改为 permissive 或 enforcing 模式时自动重新标记文件系统。以 root 用户身份使用 fixfiles -F onboot 命令创建包含 -F 选项的 /.autorelabel 文件,以确保在下次重启时重新标记文件。

在重新引导系统以进行重新标记之前,请确保系统将以 permissive 模式引导,例如使用 enforcing=0 内核选项。在启动 selinux-autorelabel 服务前,当系统包括 systemd 需要的未被标记的文件时,系统无法引导。如需更多信息,请参阅 RHBZ#2021835

2.2. 将 SELinux 更改为 permissive 模式

当 SELinux 是以 permissive 模式运行时,不会强制 SELinux 策略。系统可保持正常操作,SELinux 不会拒绝任何操作,而只是记录 AVC 信息,它们可用于故障排除、调试和 SELinux 策略改进。每个 AVC 在这个示例中仅记录一次。

先决条件

  • selinux-policy-targetedlibselinux-utilspolicycoreutils 软件包已安装在您的系统中。
  • 未使用 selinux=0enforcing=0 内核参数。

步骤

  1. 在您选择的文本编辑器中打开 /etc/selinux/config 文件,例如:

    # vi /etc/selinux/config
  2. 配置 SELINUX=permissive 选项:

    # 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=permissive
    # SELINUXTYPE= can take one of these two values:
    #       targeted - Targeted processes are protected,
    #       mls - Multi Level Security protection.
    SELINUXTYPE=targeted
  3. 重启系统:

    # reboot

验证

  1. 系统重启后,确认 getenforce 命令返回 Permissive

    $ getenforce
    Permissive

2.3. 将 SELinux 更改为 enforcing 模式

当 SELinux 处于 enforcing 模式时,它会强制 SELinux 策略并根据 SELinux 策略规则拒绝访问。在 RHEL 中,当系统最初使用 SELinux 安装时,默认启用 enforcing 模式。

先决条件

  • selinux-policy-targetedlibselinux-utilspolicycoreutils 软件包已安装在您的系统中。
  • 未使用 selinux=0enforcing=0 内核参数。

步骤

  1. 在您选择的文本编辑器中打开 /etc/selinux/config 文件,例如:

    # vi /etc/selinux/config
  2. 配置 SELINUX=enforcing 选项:

    # 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,
    #       mls - Multi Level Security protection.
    SELINUXTYPE=targeted
  3. 保存更改,重启系统:

    # reboot

    在下一次引导中,SELinux 会重新标记系统中的所有文件和目录,并为禁用 SELinux 时创建的文件和目录添加 SELinux 上下文。

验证

  1. 系统重启后,确认 getenforce 命令返回 Enforcing:

    $ getenforce
    Enforcing

故障排除

切换到 enforcing 模式后,SELinux 可能会因为不正确或缺少 SELinux 策略规则而拒绝某些操作。

  • 要查看 SELinux 拒绝的操作,以 root 用户身份输入以下命令:

    # ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts today
  • 另外,如果安装了 setroubleshoot-server 软件包,请输入:

    # grep "SELinux is preventing" /var/log/messages
  • 如果 SELinux 是活跃的,且 Audit 守护进程(auditd)没有在您的系统中运行,在 dmesg 命令输出中搜索特定的 SELinux 信息:

    # dmesg | grep -i -e type=1300 -e type=1400

如需更多信息,请参阅 SELinux 故障排除

2.4. 在之前禁用的系统中启用 SELinux

为了避免问题(如系统无法引导或进程失败),当在之前禁用的系统中启用 SELinux 时,首先在 permissive 模式中解析 Access Vector Cache (AVC)信息。

当系统以 permissive 模式运行 SELinux 时,用户和进程可能会错误地标记各种文件系统对象。当禁用 SELinux 时创建的文件系统对象不会被标记。这会在将 SELinux 改为 enforcing 模式时导致问题,因为 SELinux 依赖于正确的文件系统对象标签。

为防止错误标记和未标记的文件造成问题,SELinux 在从 disabled 状态更改为 permissive 或 enforcing 模式时自动重新标记文件系统。

警告

在重新引导系统以进行重新标记之前,请确保系统将以 permissive 模式引导,例如使用 enforcing=0 内核选项。在启动 selinux-autorelabel 服务前,当系统包括 systemd 需要的未被标记的文件时,系统无法引导。如需更多信息,请参阅 RHBZ#2021835

步骤

  1. 以 permissive 模式启用 SELinux。如需更多信息,请参阅切换到 permissive 模式
  2. 重启您的系统:

    # reboot
  3. 检查 SELinux 拒绝消息。如需更多信息,请参阅 识别 SELinux 拒绝
  4. 确保在下次重启时重新标记文件:

    # fixfiles -F onboot

    这会创建包含 -F 选项的 /.autorelabel 文件。

    警告

    进入 fixfiles -F onboot 命令前,始终切换到 permissive 模式。

    默认情况下,autorelabel 使用并行多个线程,因为系统有可用的 CPU 内核。要在自动重新标记过程中只使用单个线程,请使用 fixfiles -T 1 onboot 命令。

  5. 如果没有拒绝的操作,切换到 enforcing 模式。如需更多信息,请参阅在引导时进入 SELinux 模式

验证

  1. 系统重启后,确认 getenforce 命令返回 Enforcing:

    $ getenforce
    Enforcing

后续步骤

要在 enforcing 模式下使用 SELinux 运行自定义应用程序,请选择以下之一:

  • unconfined_service_t 域中运行您的应用程序。
  • 为应用程序编写新策略。如需更多信息,请参阅 编写自定义 SELinux 策略 部分。

其他资源

2.5. 禁用 SELinux

当您禁用 SELinux 时,您的系统不会载入 SELinux 策略。因此,系统不会强制执行 SELinux 策略,且不会记录 Access Vector Cache (AVC)信息。因此,运行 SELinux 的好处中介绍的好处都将没有。

除非在特定情况下,否则不要禁用 SELinux,如对性能敏感的系统,当弱安全性不会带来重大风险时。

重要

如果您的场景需要在生产环境中执行调试,请临时使用 permissive 模式,而不是永久禁用 SELinux。如需有关 permissive 模式的更多信息,请参阅切换为 permissive 模式

先决条件

  • 已安装 grubby 软件包:

    $ rpm -q grubby
    grubby-<version>

步骤

  1. 将您的引导装载程序配置为在内核命令行中添加 selinux=0

    $ sudo grubby --update-kernel ALL --args selinux=0
  2. 重启您的系统:

    $ reboot

验证

  • 重新引导后,确认 getenforce 命令返回 Disabled

    $ getenforce
    Disabled

2.6. 在引导时更改 SELinux 模式

在引导时,您可以设置以下内核参数来更改 SELinux 的运行方式:

enforcing=0

设置此参数可让系统以 permissive 模式启动,这在进行故障排除时非常有用。如果您的文件系统被破坏,使用 permissive 模式可能是唯一的选择。在 permissive 模式中,系统将继续正确创建标签。在这个模式中产生的 AVC 信息可能与 enforcing 模式不同。

在 permissive 模式中,只报告来自于同一拒绝的一系列操作的第一个拒绝信息。然而,在 enforcing 模式中,您可能会得到一个与读取目录相关的拒绝信息,应用程序将停止。在 permissive 模式中,您会得到相同的 AVC 信息,但应用程序将继续读取目录中的文件,并为因为每个拒绝额外获得一个 AVC。

selinux=0

这个参数会导致内核不载入 SELinux 构架的任意部分。初始化脚本会注意到系统使用 selinux=0 参数引导,并涉及 /.autorelabel 文件。这会导致系统在下次使用 SELinux enabled 模式引导时自动重新标记。

重要

不要在生产环境中使用 selinux=0 参数。要调试您的系统,请临时使用 permissive 模式而不是禁用 SELinux。

autorelabel=1

这个参数强制系统使用类似以下命令的重新标记:

# touch /.autorelabel
# reboot

如果文件系统中包含大量错误标记的对象,以 permissive 模式启动系统,使 autorelabel 进程成功。

其他资源

  • 有关 SELinux 的其他内核引导参数,如 checkreqprot,请查看由 kernel-doc 软件包安装的 /usr/share/doc/kernel-doc- <KERNEL_VER>/Documentation/admin-guide/kernel-parameters.txt 文件。使用安装的内核的版本号替换 <KERNEL_VER> 字符串,例如:

    # dnf install kernel-doc
    $ less /usr/share/doc/kernel-doc-4.18.0/Documentation/admin-guide/kernel-parameters.txt

第 3 章 管理限制和未限制的用户

每个 Linux 用户都根据 SELinux 策略中的规则映射到一个 SELinux 用户。管理员可以使用 semanage login 工具或将 Linux 用户直接分配给特定的 SELinux 用户来修改这些规则。因此,Linux 用户对其分配给的 SELinux 用户有限制。当分配给 SELinux 用户的 Linux 用户启动进程时,此过程将继承 SELinux 用户的限制,除非其他规则指定了不同的角色或类型。

3.1. SELinux 中的限制和未限制的用户

默认情况下,Red Hat Enterprise Linux 中的所有 Linux 用户(包括管理权限的用户)都会映射到无限制的 SELinux 用户 unconfined_u。您可以通过将用户分配给受 SELinux 限制的用户来提高系统安全性。

Linux 用户的安全上下文由 SELinux 用户、SELinux 角色和 SELinux 类型组成。例如:

user_u:user_r:user_t

其中:

user_u
是 SELinux 用户。
user_r
是 SELinux 角色。
user_t
是 SELinux 类型。

Linux 用户登录后,其 SELinux 用户不能改变。但是,其类型和角色可以改变,例如在转换过程中。

要在您的系统中查看 SELinux 用户映射,以 root 用户身份使用 semanage login -l 命令:

semanage login -l
Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
root                 unconfined_u         s0-s0:c0.c1023       *

在 Red Hat Enterprise Linux 中,Linux 用户默认映射到 SELinux __default__ 登录,后者映射到 SELinux unconfined_u 用户。下面一行定义了默认映射:

default          unconfined_u         s0-s0:c0.c1023       *

限制的用户受 SELinux 策略中明确定义的 SELinux 规则的限制。无限制的用户只能受到 SELinux 的最小限制。

受限制和不受限制的 Linux 用户会受到可执行和可写入的内存检查,也受到 MCS 或 MLS 的限制。

要列出可用的 SELinux 用户,请输入以下命令:

$ seinfo -u
Users: 8
   guest_u
   root
   staff_u
   sysadm_u
   system_u
   unconfined_u
   user_u
   xguest_u

请注意,seinfo 命令由 setools-console 软件包提供,该软件包默认不会安装。

如果一个未限制的 Linux 用户执行一个应用程序,这个应用程序被 SELinux 策略定义为可以从 unconfined_t 域转换到其自身限制域的应用程序,则未限制的 Linux 用户仍会受到那个受限制域的限制。这样做的安全优点是,即使 Linux 用户的运行没有限制,但应用程序仍受限制。因此,对应用程序中漏洞的利用会被策略限制。

同样,我们可以将这些检查应用到受限制的用户。每个受限制的用户都受到受限用户域的限制。SELinux 策略还可定义从受限制的用户域转换到自己受限制的目标域转换。在这种情况下,受限制的用户会受到那个目标限制的域的限制。重点是,根据用户的角色,把特定的权限与受限制的用户相关联。

3.2. SELinux 用户的角色和权限

SELinux 策略将每个 Linux 用户映射到 SELinux 用户。这允许 Linux 用户继承 SELinux 用户的限制。

您可以通过调整策略中的布尔值来自定义 SELinux 策略中受限用户的权限。您可以使用 semanage boolean -l 命令确定这些布尔值的当前状态。要列出所有 SELinux 用户、MLS 和 MCS 的级别和范围,请以 root 用户身份使用 semanage user -l 命令。

表 3.1. SELinux 用户的角色
User默认角色其他角色

unconfined_u

unconfined_r

system_r

guest_u

guest_r

 

xguest_u

xguest_r

 

user_u

user_r

 

staff_u

staff_r

sysadm_r

unconfined_r

system_r

sysadm_u

sysadm_r

 

root

staff_r

sysadm_r

unconfined_r

system_r

system_u

system_r

 

请注意,system_u 是系统进程和对象的特殊用户身份,system_r 是关联的角色。管理员不得将这个 system_u 用户和 system_r 角色关联到 Linux 用户。另外,unconfined_uroot 是没有限制的用户。因此,与这些 SELinux 用户关联的角色不会包含在下表 类型和 SELinux 角色的访问权限中。

每个 SELinux 角色都与 SELinux 类型对应,并提供特定的访问权限。

表 3.2. SELinux 角色的类型和访问权限
RoleType使用 X Window 系统登录susudo在主目录和 /tmp 中执行(默认)Networking

unconfined_r

unconfined_t

guest_r

guest_t

xguest_r

xguest_t

仅限 Web 浏览器(Mozilla Firefox、GNOME Web)

user_r

user_t

staff_r

staff_t

sudo

auditadm_r

auditadm_t

 

dbadm_r

dbadm_r

 

logadm_r

logadm_t

 

webadm_r

webadm_r

 

secadm_r

secadm_t

 

sysadm_r

sysadm_t

仅在 xdm_sysadm_login 布尔值为 on

有关非管理员用户角色的更详细描述,请参阅 SELinux 中被限制的非管理员用户角色

有关管理员角色的更详细描述,请参阅 SELinux 中受限的管理员角色

要列出所有可用角色,请输入 seinfo -r 命令:

seinfo -r
Roles: 14
   auditadm_r
   dbadm_r
   guest_r
   logadm_r
   nx_server_r
   object_r
   secadm_r
   staff_r
   sysadm_r
   system_r
   unconfined_r
   user_r
   webadm_r
   xguest_r

请注意,seinfo 命令由 setools-console 软件包提供,该软件包默认不会安装。

其他资源

3.3. SELinux 中约束的非管理员角色

在 SELinux 中,约束的非管理员角色将执行特定任务的特权和权限的特定集合授予分配给它们的 Linux 用户。通过分配单独的约束的非管理员角色,您可以将特定的特权分配给单个用户。这在有多个有不同授权级别的用户时很有用。

您还可以通过更改系统上相关的 SELinux 布尔值来自定义 SELinux 角色的权限。要查看 SELinux 布尔值及其状态,请以 root 用户身份使用 semanage boolean -l 命令。如果安装了 selinux-policy-devel 软件包,您可以获得更详细的描述。

# semanage boolean -l
SELinux boolean                State  Default Description
…
xguest_connect_network         (on   ,   on)  Allow xguest users to configure Network Manager and connect to apache ports
xguest_exec_content            (on   ,   on)  Allow xguest to exec content
…

user_tguest_txguest_t 域中的 Linux 用户只能在 SELinux 策略允许的情况下运行设置用户 ID (setuid)应用程序(例如 passwd)。这些用户无法运行 setuid 应用程序 susudo,因此无法使这些应用程序变为 root 用户。

默认情况下,staff_tuser_tguest_txguest_t 域中的 Linux 用户可以在其主目录和 /tmp 中执行应用程序。应用程序继承执行它们的用户的权限。

要防止 guest_txguest_t 用户在其有写权限的目录中执行应用程序,请将 guest_exec_contentxguest_exec_content 布尔值设置为 off

SELinux 有以下约束的非管理员角色,每个角色都有特定的特权和限制:

guest_r

有非常有限的权限。分配给此角色的用户无法访问网络,但可以执行 /tmp/home 目录中的文件。

相关的布尔值:

SELinux boolean                State  Default Description
guest_exec_content             (on   ,   on)  Allow guest to exec content
xguest_r

有有限的权限。分配给此角色的用户可以登录到 X 窗口,使用网络浏览器访问网页和访问介质。它们也可以执行 /tmp/home 目录中的文件。

相关的布尔值:

SELinux boolean                State  Default Description
xguest_connect_network         (on   ,   on)  Allow xguest users to configure Network Manager and connect to apache ports
xguest_exec_content            (on   ,   on)  Allow xguest to exec content
xguest_mount_media             (on   ,   on)  Allow xguest users to mount removable media
xguest_use_bluetooth           (on   ,   on)  Allow xguest to use blue tooth devices
user_r

有具有完整用户权限的非特权访问权限。分配给此角色的用户可以执行大多数不需要管理特权的操作。

相关的布尔值:

SELinux boolean                State  Default Description
unprivuser_use_svirt           (off  ,  off)  Allow unprivileged user to create and transition to svirt domains.
staff_r

具有类似于 user_r 的权限和其他特权。特别是,分配给此角色的用户被允许运行 sudo 来执行通常为 root 用户保留的管理命令。这会更改角色和有效的用户 ID (EUID),但不更改 SELinux 用户。

相关的布尔值:

SELinux boolean                State  Default Description
staff_exec_content             (on   ,   on)  Allow staff to exec content
staff_use_svirt                (on   ,   on)  allow staff user to create and transition to svirt domains.

其他资源

  • 要将 Linux 用户映射到 staff_u 并配置 sudo,请参阅 使用 sudo 和 sysadm_r 角色配置管理员
  • 有关每个角色和相关类型的详情,请查看 selinux-policy-doc 软件包安装的相关手册页:

    guest_selinux (8), xguest_selinux (8), user_selinux (8), 和 staff_selinux (8)

3.4. SELinux 中受限的管理员角色

在 SELinux 中,受限制的管理员角色将执行特定任务的特定的特权和权限集合授权给分配给它们的 Linux 用户。通过分配单独的受限制的管理员角色,您可以将不同系统管理域上的权限划分给单个用户。这在有多个管理员的情况下很有用,每个管理员都有单独的域。

您可以使用 semanage user 命令将这些角色分配给 SELinux 用户。

SELinux 有以下受限制的管理员角色:

auditadm_r

审计管理员角色允许管理与审计子系统相关的进程。

相关的布尔值:

SELinux boolean                State  Default Description
auditadm_exec_content          (on   ,   on)  Allow auditadm to exec content
dbadm_r

数据库管理员角色允许管理 MariaDB 和 PostgreSQL 数据库。

相关的布尔值:

SELinux boolean                State  Default Description
dbadm_exec_content             (on   ,   on)  Allow dbadm to exec content
dbadm_manage_user_files        (off  ,  off)  Determine whether dbadm can manage generic user files.
dbadm_read_user_files          (off  ,  off)  Determine whether dbadm can read generic user files.
logadm_r

日志管理员角色允许管理日志,特别是与 Rsyslog 日志记录服务和审计子系统相关的 SELinux 类型。

相关的布尔值:

SELinux boolean                State  Default Description
logadm_exec_content            (on   ,   on)  Allow logadm to exec content
webadm_r

Web 管理员允许管理 Apache HTTP 服务器。

相关的布尔值:

SELinux boolean                State  Default Description
webadm_manage_user_files       (off  ,  off)  Determine whether webadm can manage generic user files.
webadm_read_user_files         (off  ,  off)  Determine whether webadm can read generic user files.
secadm_r

安全管理员角色允许管理 SELinux 数据库。

相关的布尔值:

SELinux boolean                State  Default Description
secadm_exec_content            (on   ,   on)  Allow secadm to exec content
sysadm_r

系统管理员角色允许执行之前列出的角色的任何操作,并具有额外的特权。在非默认配置中,可以通过在 SELinux 策略中禁用 sysadm_secadm 模块来将安全管理与系统管理分开。具体步骤请参阅 MLS 中的从安全管理分离系统管理

sysadm_u 用户无法使用 SSH 直接登录。要为 sysadm_u 启用 SSH 登录,请将 ssh_sysadm_login 布尔值设置为 on

# setsebool -P ssh_sysadm_login on

相关的布尔值:

SELinux boolean                State  Default Description
ssh_sysadm_login               (on   ,   on)  Allow ssh logins as sysadm_r:sysadm_t
sysadm_exec_content            (on   ,   on)  Allow sysadm to exec content
xdm_sysadm_login               (on   ,   on)  Allow the graphical login program to login directly as sysadm_r:sysadm_t

其他资源

  • 要将 Linux 用户分配给受限管理员角色,请参阅通过 映射到 sysadm_u 来限制管理员
  • 有关每个角色以及相关类型的详情,请查看 selinux-policy-doc 软件包安装的相关手册页:

    auditadm_selinux (8), dbadm_selinux (8), logadm_selinux (8), webadm_selinux (8), secadm_selinux (8), 和 sysadm_selinux (8)

3.5. 添加一个新用户会自动映射到 SELinux unconfined_u 用户

下面的步骤演示了如何在系统中添加新 Linux 用户。用户会自动映射到 SELinux unconfined_u 用户。

先决条件

  • root 用户运行没有限制,这在 Red Hat Enterprise Linux 中默认运行。

步骤

  1. 输入以下命令创建一个名为 <example_user> 的新 Linux 用户:

    useradd <example_user>
  2. 为 Linux <example_user> 用户分配一个密码:

    passwd <example_user>
    Changing password for user <example_user>.
    New password:
    Retype new password:
    passwd: all authentication tokens updated successfully.
  3. 退出当前会话。
  4. 以 Linux <example_user> 用户身份登录。当您登录时,pam_selinux PAM 模块会自动将 Linux 用户映射到 SELinux 用户(本例中为 unconfined_u),并设置生成的 SELinux 上下文。然后会使用这个上下文启动 Linux 用户的 shell。

验证

  1. <example_user> 用户身份登录时,请检查 Linux 用户的上下文:

    $ id -Z
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

其他资源

  • 系统中的 pam_selinux (8) 手册页

3.6. 以 SELinux 限制的用户身份添加新用户

使用以下步骤为该系统添加新的 SELinux 保护用户。这个示例步骤会在创建用户帐户后马上将用户映射到 SELinux staff_u 用户。

先决条件

  • root 用户运行没有限制,这在 Red Hat Enterprise Linux 中默认运行。

步骤

  1. 输入以下命令创建一个名为 <example_user> 的新 Linux 用户,并将其映射到 SELinux staff_u 用户:

    useradd -Z staff_u <example_user>
  2. 为 Linux <example_user> 用户分配一个密码:

    passwd <example_user>
    Changing password for user <example_user>.
    New password:
    Retype new password:
    passwd: all authentication tokens updated successfully.
  3. 退出当前会话。
  4. 以 Linux <example_user> 用户身份登录。用户的 shell 使用 staff_u 上下文启动。

验证

  1. <example_user> 用户身份登录时,请检查 Linux 用户的上下文:

    $ id -Z
    uid=1000(<example_user>) gid=1000(<example_user>) groups=1000(<example_user>) context=staff_u:staff_r:staff_t:s0-s0:c0.c1023

其他资源

  • 系统中的 pam_selinux (8) 手册页

3.7. 在 SELinux 中限制常规用户

您可以通过将系统映射到 user_u SELinux 用户来限制系统中的所有常规用户。

默认情况下,Red Hat Enterprise Linux 中的所有 Linux 用户(包括管理权限的用户)都会映射到无限制的 SELinux 用户 unconfined_u。您可以通过将用户分配给受 SELinux 限制的用户来提高系统安全性。这对遵守 V-71971 安全技术实施指南非常有用。

步骤

  1. 显示 SELinux 登录记录列表。这个列表显示了 Linux 用户与 SELinux 用户的映射:

    # semanage login -l
    
    Login Name    SELinux User  MLS/MCS Range   Service
    
    __default__   unconfined_u  s0-s0:c0.c1023       *
    root          unconfined_u  s0-s0:c0.c1023       *
  2. __default__ 用户(表示没有显式映射的所有用户)映射到 user_u SELinux 用户:

    # semanage login -m -s user_u -r s0 __default__

验证

  1. 检查 __default__ 用户是否已映射到 user_u SELinux 用户:

    # semanage login -l
    
    Login Name    SELinux User   MLS/MCS Range    Service
    
    __default__   user_u         s0               *
    root          unconfined_u   s0-s0:c0.c1023   *
  2. 验证新用户的进程在 user_u:user_r:user_t:s0 SELinux 上下文中运行。

    1. 创建一个新用户:

      # adduser <example_user>
    2. <example_user> 定义一个密码:

      # passwd <example_user>
    3. 注销 root,然后以新用户身份登录。
    4. 显示用户 ID 的安全上下文:

      [<example_user>@localhost ~]$ id -Z
      user_u:user_r:user_t:s0
    5. 显示用户当前进程的安全上下文:

      [<example_user>@localhost ~]$ ps axZ
      LABEL                           PID TTY      STAT   TIME COMMAND
      -                                 1 ?        Ss     0:05 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
      -                              3729 ?        S      0:00 (sd-pam)
      user_u:user_r:user_t:s0        3907 ?        Ss     0:00 /usr/lib/systemd/systemd --user
      -                              3911 ?        S      0:00 (sd-pam)
      user_u:user_r:user_t:s0        3918 ?        S      0:00 sshd: <example_user>@pts/0
      user_u:user_r:user_t:s0        3922 pts/0    Ss     0:00 -bash
      user_u:user_r:user_dbusd_t:s0  3969 ?        Ssl    0:00 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
      user_u:user_r:user_t:s0        3971 pts/0    R+     0:00 ps axZ

3.8. 通过映射到 sysadm_u来限制管理员

您可以通过将用户直接映射到 sysadm_u SELinux 用户来限制具有管理权限的用户。当用户登录时,会话会在 sysadm_u:sysadm_r:sysadm_t SELinux 上下文中运行。

默认情况下,Red Hat Enterprise Linux 中的所有 Linux 用户(包括管理权限的用户)都会映射到无限制的 SELinux 用户 unconfined_u。您可以通过将用户分配给受 SELinux 限制的用户来提高系统安全性。这对遵守 V-71971 安全技术实施指南非常有用。

先决条件

  • root 用户运行没有限制。这是 Red Hat Enterprise Linux 的默认设置。

步骤

  1. 可选:要允许 sysadm_u 用户使用 SSH 连接到系统:

    # setsebool -P ssh_sysadm_login on
  2. 将新用户映射到 sysadm_u SELinux 用户:

    • 要映射新用户,请在 wheel 用户组中添加一个新用户,并将用户映射到 sysadm_u SELinux 用户:

      # adduser -G wheel -Z sysadm_u <example_user>
    • 要映射现有用户,将用户添加到 wheel 用户组,并将用户映射到 sysadm_u SELinux 用户:

      # usermod -G wheel -Z sysadm_u <example_user>
  3. 恢复用户主目录的上下文:

    # restorecon -R -F -v /home/<example_user>

验证

  1. 检查 <example_user> 是否被映射到 sysadm_u SELinux 用户:

    # semanage login -l | grep <example_user>
    <example_user>     sysadm_u    s0-s0:c0.c1023   *
  2. <example_user> 身份登录,例如使用 SSH,并显示用户的安全上下文:

    [<example_user>@localhost ~]$ id -Z
    sysadm_u:sysadm_r:sysadm_t:s0-s0:c0.c1023
  3. 切换到 root 用户:

    $ sudo -i
    [sudo] password for <example_user>:
  4. 验证安全性上下文是否保持不变:

    # id -Z
    sysadm_u:sysadm_r:sysadm_t:s0-s0:c0.c1023
  5. 尝试管理任务,例如重启 sshd 服务:

    # systemctl restart sshd

    如果没有输出结果,则代表命令可以成功完成。

    如果该命令没有成功完成,它会输出以下信息:

    Failed to restart sshd.service: Access denied
    See system logs and 'systemctl status sshd.service' for details.

3.9. 使用 sudo 和 sysadm_r 角色约束管理员

您可以将具有管理权限的特定用户映射到 staff_u SELinux 用户,并配置 sudo,以便用户获取 sysadm_r SELinux 管理员角色。这个角色允许用户在不拒绝 SELinux 的情况下执行管理任务。当用户登录时,会话运行在 staff_u:staff_r:staff_r:staff_t SELinux 上下文中,但当用户使用 sudo 输入命令时,会话会更改为 staff_u:sysadm_r:sysadm_t 上下文。

默认情况下,Red Hat Enterprise Linux 中的所有 Linux 用户(包括管理权限的用户)都会映射到无限制的 SELinux 用户 unconfined_u。您可以通过将用户分配给受 SELinux 限制的用户来提高系统安全性。这对遵守 V-71971 安全技术实施指南非常有用。

先决条件

  • root 用户运行没有限制。这是 Red Hat Enterprise Linux 的默认设置。

步骤

  1. 将新用户或现有用户映射到 staff_u SELinux 用户:

    1. 要映射新用户,请将新用户添到 wheel 用户组,并将用户映射到 staff_u SELinux 用户:

      # adduser -G wheel -Z staff_u <example_user>
    2. 要映射现有用户,请将用户添加到 wheel 用户组,并将用户映射到 staff_u SELinux 用户:

      # usermod -G wheel -Z staff_u <example_user>
  2. 恢复用户主目录的上下文:

    # restorecon -R -F -v /home/<example_user>
  3. 要允许 <example_user> 获得 SELinux 管理员角色,请在 /etc/sudoers.d/ 目录中创建一个新文件,例如:

    # visudo -f /etc/sudoers.d/<example_user>
  4. 在新文件中添加以下行:

    <example_user> ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL

验证

  1. 检查 <example_user> 是否已映射到 staff_u SELinux 用户:

    # semanage login -l | grep <example_user>
    <example_user>     staff_u    s0-s0:c0.c1023   *
  2. <example_user> 身份登录,例如使用 SSH,并切换到 root 用户:

    [<example_user>@localhost ~]$ sudo -i
    [sudo] password for <example_user>:
  3. 显示 root 安全上下文:

    # id -Z
    staff_u:sysadm_r:sysadm_t:s0-s0:c0.c1023
  4. 尝试管理任务,例如重启 sshd 服务:

    # systemctl restart sshd

    如果没有输出结果,则代表命令可以成功完成。

    如果该命令没有成功完成,它会输出以下信息:

    Failed to restart sshd.service: Access denied
    See system logs and 'systemctl status sshd.service' for details.

3.10. 其他资源

第 4 章 为使用非标准配置的应用程序和服务配置 SELinux

当 SELinux 处于 enforcing 模式时,默认策略是目标(targeted)策略。以下小节提供了有关在更改配置默认值后为各种服务设置和配置 SELinux 策略的信息,如端口、数据库位置或进程的文件系统权限。

您将了解如何为非标准端口更改 SELinux 类型,识别并修复默认目录更改的不正确的标签,以及使用 SELinux 布尔值调整策略。

4.1. 在非标准配置中为 Apache HTTP 服务器自定义 SELinux 策略

您可以将 Apache HTTP 服务器配置为在不同端口中侦听,并在非默认目录中提供内容。要防止 SELinux 拒绝带来的后果,请按照以下步骤调整系统的 SELinux 策略。

先决条件

  • 已安装 httpd 软件包,并将 Apache HTTP 服务器配置为侦听 TCP 端口 3131,并使用 /var/test_www/ 目录而不是默认的 /var/www/ 目录。
  • policycoreutils-python-utilssetroubleshoot-server 软件包已安装在您的系统中。

步骤

  1. 启动 httpd 服务并检查状态:

    # systemctl start httpd
    # systemctl status httpd
    ...
    httpd[14523]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:3131
    ...
    systemd[1]: Failed to start The Apache HTTP Server.
    ...
  2. SELinux 策略假设 httpd 在端口 80 上运行:

    # semanage port -l | grep http
    http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010
    http_cache_port_t              udp      3130
    http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
    pegasus_http_port_t            tcp      5988
    pegasus_https_port_t           tcp      5989
  3. 更改 SELinux 类型端口 3131 使其与端口 80 匹配:

    # semanage port -a -t http_port_t -p tcp 3131
  4. 再次启动 httpd

    # systemctl start httpd
  5. 但是,内容仍无法访问:

    # wget localhost:3131/index.html
    ...
    HTTP request sent, awaiting response... 403 Forbidden
    ...

    使用 sealert 工具查找原因:

    # sealert -l "*"
    ...
    SELinux is preventing httpd from getattr access on the file /var/test_www/html/index.html.
    ...
  6. 使用 matchpathcon 工具比较标准 SELinux 类型以及新路径:

    # matchpathcon /var/www/html /var/test_www/html
    /var/www/html       system_u:object_r:httpd_sys_content_t:s0
    /var/test_www/html  system_u:object_r:var_t:s0
  7. 将新 /var/test_www/html/ 内容目录的 SELinux 类型改为默认 /var/www/html 目录的类型:

    # semanage fcontext -a -e /var/www /var/test_www
  8. 递归重新标记 /var 目录:

    # restorecon -Rv /var/
    ...
    Relabeled /var/test_www/html from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
    Relabeled /var/test_www/html/index.html from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

验证

  1. 检查 httpd 服务是否正在运行:

    # systemctl status httpd
    ...
    Active: active (running)
    ...
    systemd[1]: Started The Apache HTTP Server.
    httpd[14888]: Server configured, listening on: port 3131
    ...
  2. 验证 Apache HTTP 服务器提供的内容是否可以访问:

    # wget localhost:3131/index.html
    ...
    HTTP request sent, awaiting response... 200 OK
    Length: 0 [text/html]
    Saving to: ‘index.html’
    ...

其他资源

  • semanage (8), matchpathcon (8), 和 sealert (8) man pages.

4.2. 使用 SELinux 布尔值调整用于共享 NFS 和 CIFS 卷的策略

您可以使用布尔值在运行时更改 SELinux 策略部分,即使您不了解 SELinux 策略的编写方式。这启用了更改,比如允许服务访问 NFS 卷而无需重新载入或者重新编译 SELinux 策略。以下流程演示了列出 SELinux 布尔值并进行配置,以实现策略中所需的更改。

在客户端的 NFS 挂载使用 NFS 卷策略定义的默认上下文标记。在 RHEL 中,此默认上下文使用 nfs_t 类型。另外,挂载在客户端中的 Samba 共享使用策略定义的默认上下文标记。此默认上下文使用 cifs_t 类型。您可以启用或禁用布尔值来控制允许哪些服务访问 nfs_tcifs_t 类型。

要允许 Apache HTTP 服务器服务(httpd)访问和共享 NFS 和 CIFS 卷,请执行以下步骤:

先决条件

  • (可选)安装 selinux-policy-devel 软件包,以获取 semanage boolean -l 命令的输出中 SELinux 布尔值的更清晰和详细描述。

步骤

  1. 识别与 NFS、CIFS 和 Apache 相关的 SELinux 布尔值:

    # semanage boolean -l | grep 'nfs\|cifs' | grep httpd
    httpd_use_cifs                 (off  ,  off)  Allow httpd to access cifs file systems
    httpd_use_nfs                  (off  ,  off)  Allow httpd to access nfs file systems
  2. 列出布尔值的当前状态:

    $ getsebool -a | grep 'nfs\|cifs' | grep httpd
    httpd_use_cifs --> off
    httpd_use_nfs --> off
  3. 启用指定的布尔值:

    # setsebool httpd_use_nfs on
    # setsebool httpd_use_cifs on
    注意

    使用 setsebool-P 选项,使更改在重新启动后仍然有效。setsebool -P 命令需要重建整个策略,且可能需要一些时间,具体取决于您的配置。

验证

  1. 检查布尔值为 on

    $ getsebool -a | grep 'nfs\|cifs' | grep httpd
    httpd_use_cifs --> on
    httpd_use_nfs --> on

其他资源

  • semanage-boolean (8), sepolicy- booleans (8) , getsebool (8), setsebool (8), booleans (5), 和 booleans (8) man pages

4.3. 查找用于管理对非标准目录的访问的正确 SELinux 类型

如果您需要设置默认 SELinux 策略没有涵盖的访问控制规则,请首先搜索与您的用例匹配的布尔值。如果您无法找到合适的布尔值,您可以使用匹配的 SELinux 类型甚至创建本地策略模块。

先决条件

  • selinux-policy-docsetools-console 软件包已安装在您的系统中。

步骤

  1. 列出所有与 SELinux 相关的主题,并将结果限制为您要配置的组件。例如:

    # man -k selinux | grep samba
    samba_net_selinux (8) - Security Enhanced Linux Policy for the samba_net processes
    samba_selinux (8)    - Security Enhanced Linux Policy for the smbd processes
    …

    在与您的场景对应的 man page 中,找到相关的 SELinux 布尔值、端口类型和文件类型。

    请注意,只有安装 selinux-policy-doc 软件包后,man -k selinuxapropos selinux 命令才可用。

  2. 可选:您可以使用 semanage fcontext -l 命令显示默认位置上进程的默认映射,例如:

    # semanage fcontext -l | grep samba
    …
    /var/cache/samba(/.*)?                             all files          system_u:object_r:samba_var_t:s0
    …
    /var/spool/samba(/.*)?                             all files          system_u:object_r:samba_spool_t:s0
    …
  3. 使用 sesearch 命令显示默认 SELinux 策略中的规则。您可以通过列出对应的规则来查找要使用的类型和布尔值,例如:

    $ sesearch -A | grep samba | grep httpd
    …
    allow httpd_t cifs_t:dir { getattr open search }; [ use_samba_home_dirs && httpd_enable_homedirs ]:True
    …
  4. SELinux 布尔值可能是您的配置问题最直接的解决方案。您可以使用 getsebool -a 命令显示所有可用的布尔值及其值,例如:

    $ getsebool -a | grep homedirs
    git_cgi_enable_homedirs --> off
    git_system_enable_homedirs --> off
    httpd_enable_homedirs --> off
    mock_enable_homedirs --> off
    mpd_enable_homedirs --> off
    openvpn_enable_homedirs --> on
    ssh_chroot_rw_homedirs --> off
  5. 您可以使用 sesearch 命令验证所选布尔值是否准确执行所需的内容,例如:

    $ sesearch -A | grep httpd_enable_homedirs
    …
    allow httpd_suexec_t autofs_t:dir { getattr open search }; [ use_nfs_home_dirs && httpd_enable_homedirs ]:True
    allow httpd_suexec_t autofs_t:dir { getattr open search }; [ use_samba_home_dirs && httpd_enable_homedirs ]:True
    …
  6. 如果没有与您的场景匹配,则找到适合您问题单的 SELinux 类型。您可以使用 sesearch 从默认策略查询对应的规则来查找您的文件类型,例如:

    $ sesearch -A -s httpd_t -c file -p read
    …
    allow httpd_t httpd_t:file { append getattr ioctl lock open read write };
    allow httpd_t httpd_tmp_t:file { append create getattr ioctl link lock map open read rename setattr unlink write };
    …
  7. 如果前面的解决方案没有满足您的场景,您可以在 SELinux 策略中添加自定义规则。如需更多信息 ,请参阅创建本地 SELinux 策略模块 部分。

其他资源

  • man -k selinux 命令提供的与 SELinux 相关的 man page
  • sesearch (1), semanage-fcontext (8), semanage-boolean (8), 和 getsebool (8) 手册页

4.4. 为非特权用户管理对非标准共享目录的访问

您可以通过查找和映射对应的 SELinux 文件类型,为通用非特权 SELinux 用户 user_u 配置对非标准共享目录的访问。user_u 用户具有默认角色 user_r 和默认域 user_t

先决条件

  • selinux-policy-docsetools-console 软件包已安装在您的系统中。

步骤

  1. 在终端中打开 user_selinux (8) 手册页:

    $ man user_selinux

    MANAGED FILES 部分中,找到与您的场景对应的属性或类型。例如,user_home_type 属性。

  2. 可选:要列出分配给属性的所有类型,请使用 seinfo 命令和 -x-a 选项,例如:

    $ seinfo -x -a user_home_type
    
    Type Attributes: 1
       attribute user_home_type;
    …
    	chrome_sandbox_home_t
    	config_home_t
    	cvs_home_t
    	data_home_t
    	dbus_home_t
    	fetchmail_home_t
    	gconf_home_t
    	git_user_content_t
    …
  3. 在找到相应类型的候选后,本例中的 data_home_t 类型会检查其 SELinux 映射:

    $ semanage fcontext -l | grep data_home_t
    …
    /root/\.local/share(/.*)?                          all files          system_u:object_r:data_home_t:s0
    …
  4. 将对应的类型映射到您要供 user_u 访问的目录,例如 /shared-data

    $ semanage fcontext -a -t data_home_t '/shared-data(/.*)?'

验证

  1. 检查您配置的目录的映射:

    # semanage fcontext -l | grep "shared-data"
    /shared-data(/.*)?                             	all files      	system_u:object_r:data_home_t:s0
  2. 以映射到 user_u SELinux 用户的 Linux 用户身份登录,并验证您可以访问该目录。

其他资源

第 6 章 使用多级别安全(MLS)

多级别安全(Multi-Level Security,简称 MLS)策略使用许可级别的概念,这个概念首先由美国国防人员设计。MLS 满足一组非常严格的安全要求,这基于在严格控制的环境中管理的信息(如军事)。

使用 MLS 非常复杂,不适合于一般用例场景。

6.1. 多级别安全(MLS)

多级别安全(MLS)技术使用信息安全级别将数据分为分级分类,例如:

  • [Low] 非保密
  • [low] 保密
  • [high] 机密
  • [Highest] 顶端机密

默认情况下,MLS SELinux 策略使用 16 敏感度级别:

  • s0 是最敏感的。
  • s15 是最敏感的。

MLS 使用特定的术语来代表敏感度级别:

  • 用户和进程称为 主题(subjects),其敏感度级别被称为 安全权限(clearance)
  • 系统文件、设备和其他被动组件称为 对象(objects),其敏感度级别被称为安全级别(classification)

为了实施 MLS,SELinux 使用 Bell-La Padula Model (BLP)模型。这个模型根据附加到每个主体和对象的标签指定系统中如何进行信息流。

BLP 的基本原则是"不能从上面读取,不能向下面写入”。这意味着用户只能读取自己的敏感度级别及更低级别的文件,数据只能从较低级别流入到更高级别,且不会从高级别流向低级别。

MLS SELinux 策略(RHEL 中的 MLS 实现)应用一个名为 Bell-La Padula with write equality 的经过修改的原则。这意味着,用户可以在自己的敏感度级别和更低级别中读取文件,但只能在自己的级别上写入。例如,这可以防止不明确的用户将内容写入 top-secret 文件中。

例如,默认情况下,具有安全许可级别 s2 的用户:

  • 可以读取敏感度级别为 s0s1s2 的文件。
  • 无法读取敏感度级别为 s3 及更高等级的文件。
  • 可以修改敏感级别为 s2 的文件。
  • 无法修改敏感级别不是 s2 的文件。
注意

安全管理员可以通过修改系统的 SELinux 策略来调整此行为。例如,可以允许用户修改更低级别的文件,这需要将文件的敏感级别增加到用户的安全许可级别。

实际上,用户通常会被分配为具有一系列的安全许可级别,如 s1-s2。用户可以读取级别低于用户的最大级别的文件,并可以写入该范围内的任何文件。

例如,默认情况下,用户有一个安全许可级别范围 s1-s2

  • 可以读取具有敏感度级别 s0s1 的文件。
  • 不能读取级别 s2 及更高等级的文件。
  • 可以修改具有敏感度级别 s1 的文件。
  • 无法修改敏感级别不是 s1 的文件。
  • 可以将自己的安全许可级别更改为 s2

MLS 环境中非特权用户的安全上下文是:

user_u:user_r:user_t:s1

其中:

user_u
是 SELinux 用户。
user_r
是 SELinux 角色。
user_t
是 SELinux 类型。
s1
是 MLS 敏感级别的范围。

系统始终将 MLS 访问规则与传统的文件访问权限合并。例如,如果具有安全级别 "Secret" 的用户使用 Discretionary Access Control(DAC)来阻止其他用户对文件的访问,即使"Top Secret"用户无法访问该文件。较高的安全许可不会自动允许用户浏览整个文件系统。

拥有顶级别的用户不会自动获得多级系统的管理权限。虽然他们可以访问有关系统的所有敏感信息,但这与具有管理权限不同。

此外,管理权限不提供对敏感信息的访问权限。例如,即使某人以 root 身份登录,它们仍然无法读取 top-secret 信息。

您可以使用类别进一步调整 MLS 系统中的访问。使用多类别安全性(MCS),您可以定义项目或部门等类别,用户只能访问为其分配的类别中的文件。如需更多信息,请参阅 使用多类别 Security(MCS)获取数据保密性

6.2. MLS 中的 SELinux 角色

SELinux 策略将每个 Linux 用户映射到 SELinux 用户。这允许 Linux 用户继承 SELinux 用户的限制。

重要

MLS 策略不包含 unconfined 模块,包括无限制的用户、类型和角色。因此,用户将不受限制(包括 root )的用户无法访问每个对象,并执行他们在目标策略中可以进行的每个操作。

您可以通过调整策略中的布尔值来自定义 SELinux 策略中受限用户的权限。您可以使用 semanage boolean -l 命令确定这些布尔值的当前状态。要列出所有 SELinux 用户、其 SELinux 角色和 MLS/MCS 级别和范围,以 root 用户身份使用 semanage user -l 命令。

表 6.1. MLS 中 SELinux 用户的角色
User默认角色其他角色

guest_u

guest_r

 

xguest_u

xguest_r

 

user_u

user_r

 

staff_u

staff_r

auditadm_r

secadm_r

sysadm_r

staff_r

sysadm_u

sysadm_r

 

root

staff_r

auditadm_r

secadm_r

sysadm_r

system_r

system_u

system_r

 

请注意,system_u 是系统进程和对象的特殊用户身份,system_r 是关联的角色。管理员不得将这个 system_u 用户和 system_r 角色关联到 Linux 用户。另外,unconfined_uroot 是没有限制的用户。因此,与这些 SELinux 用户关联的角色不会包含在下表中 type 和 SELinux 角色的访问中。

每个 SELinux 角色都与 SELinux 类型对应,并提供特定的访问权限。

表 6.2. MLS 中 SELinux 角色的类型和访问
RoleType使用 X 窗口系统登录susudo在主目录和 /tmp 中执行(默认)Networking

guest_r

guest_t

xguest_r

xguest_t

仅限 Web 浏览器(Firefox、GNOME Web)

user_r

user_t

staff_r

staff_t

sudo

auditadm_r

auditadm_t

 

secadm_r

secadm_t

 

sysadm_r

sysadm_t

仅在 xdm_sysadm_login 布尔值为 on

  • 默认情况下,sysadm_r 角色具有 secadm_r 角色的权限,这意味着具有 sysadm_r 角色的用户可以管理安全策略。如果这没有与您的用例对应,您可以通过在策略中禁用 sysadm_secadm 模块来分离这两个角色。如需更多信息,请参阅 MLS 中的从安全管理分离系统管理
  • 非登录角色 dbadm_rlogadm_rwebadm_r 可用于管理任务的子集。默认情况下,这些角色不与任何 SELinux 用户关联。

6.3. 将 SELinux 策略切换到 MLS

使用以下步骤将 SELinux 策略从 targeted 切换到多级别安全(MLS)。

重要

不要在运行 X 窗口系统的系统中使用 MLS 策略。另外,当您使用 MLS 标签重新标记文件系统时,系统可能会阻止受限制的域访问,这会阻止您的系统正确启动。因此请确定您在重新标记文件前将 SELinux 切换到 permissive 模式。在大多数系统中,您会看到在切换到 MLS 后出现了很多 SELinux 拒绝信息,且其中很多都不容易修复。

步骤

  1. 安装 selinux-policy-mls 软件包:

    # dnf install selinux-policy-mls
  2. 在您选择的文本编辑器中打开 /etc/selinux/config 文件,例如:

    # vi /etc/selinux/config
  3. 将 SELinux 模式从 enforcing 改为 permissive,并从 targeted 策略切换到 MLS:

    SELINUX=permissive
    SELINUXTYPE=mls

    保存更改,退出编辑器。

  4. 在启用 MLS 策略前,您必须使用 MLS 标签重新标记文件系统中的每个文件:

    # fixfiles -F onboot
    System will relabel on next boot
  5. 重启系统:

    # reboot
  6. 检查 SELinux 拒绝信息:

    # ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent -i

    因为前面的命令没有涵盖所有情况,请参阅 SELinux 故障排除中有关识别、分析以及修复 SELinux 拒绝的指导。

  7. 在确定您的系统中没有与 SELinux 相关的问题后,通过更改 /etc/selinux/config 中的对应选项将 SELinux 切换回 enforcing 模式:

    SELINUX=enforcing
  8. 重启系统:

    # reboot
重要

如果您的系统没有启动,或者您无法在切换到 MLS 后登录,请将 enforcing=0 参数添加到内核命令行。如需更多信息,请参阅在引导时更改 SELinux 模式

另请注意,在 MLS 中,以 root 用户身份通过 SSH 登录映射到 sysadm_r SELinux 角色,它与作为 staff_r 中的 root 登录不同。在 MLS 中首次启动系统前,请考虑通过将 ssh_sysadm_login SELinux 布尔值设置为 1 来允许以 sysadm_r 身份登录 SSH 登录。要稍后才启用 ssh_sysadm_login(已在 MLS 中),您需要在 staff_r 中以 root 身份登陆,使用 newrole -r sysadm_r 命令切换到 sysadm_r 中的 root,然后将布尔值设置为 1

验证

  1. 验证 SELinux 是否在 enforcing 模式下运行:

    # getenforce
    Enforcing
  2. 检查 SELinux 的状态是否返回 mls 值:

    # sestatus | grep mls
    Loaded policy name:             mls

其他资源

  • fixfiles (8), setsebool (8), 和 ssh_selinux (8) man page

6.4. 在 MLS 中建立用户明确

将 SELinux 策略切换到 MLS 后,必须通过将 SELinux 策略映射到受限的 SELinux 用户来为用户分配安全清晰级别。默认情况下,具有给定安全许可的用户:

  • 不能读取具有更高敏感度级别的对象。
  • 无法写入具有不同敏感度级别的对象。

先决条件

  • SELinux 策略被设置为 mls
  • SELinux 模式设置为 enforcing
  • 已安装 policycoreutils-python-utils 软件包。
  • 分配给 SELinux 受限用户的用户:

    • 对于非授权用户,分配给 user_u (以下流程中的example_user )。
    • 对于特权用户,分配给 staff_u (以下流程中的 staff )。
重要

确保 MLS 策略处于活动状态时已创建该用户。MLS 中无法使用在其他 SELinux 策略中创建的用户。

步骤

  1. 可选:要防止向 SELinux 策略添加错误,切换到 permissive SELinux 模式,这有助于进行故障排除:

    # setenforce 0

    请注意,在 permissive 模式中,SELinux 不强制执行活跃策略,而是只记录 Access Vector Cache (AVC)信息,然后可用于故障排除和调试。

  2. staff_u SELinux 用户定义清晰的范围。例如,这个命令会将安全权限范围设置为 s1s15s1 是默认的安全权限级别:

    # semanage user -m -L s1 -r s1-s15 staff_u
  3. 为用户主目录生成 SELinux 文件上下文配置条目:

    # genhomedircon
  4. 将文件安全上下文恢复到默认值:

    # restorecon -R -F -v /home/
    Relabeled /home/staff from staff_u:object_r:user_home_dir_t:s0 to staff_u:object_r:user_home_dir_t:s1
    Relabeled /home/staff/.bash_logout from staff_u:object_r:user_home_t:s0 to staff_u:object_r:user_home_t:s1
    Relabeled /home/staff/.bash_profile from staff_u:object_r:user_home_t:s0 to staff_u:object_r:user_home_t:s1
    Relabeled /home/staff/.bashrc from staff_u:object_r:user_home_t:s0 to staff_u:object_r:user_home_t:s1
  5. 为用户分配安全权限级别:

    # semanage login -m -r s1 example_user

    其中 s1 是分配给用户的安全权限级别。

  6. 将用户的主目录重新标记到用户的明确级别:

    # chcon -R -l s1 /home/example_user
  7. 可选:如果您之前切换到 permissive SELinux 模式,并在验证所有内容可以正常工作后,切换回 enforcing SELinux 模式:

    # setenforce 1

验证

  1. 验证用户是否已映射到正确的 SELinux 用户,并分配了正确的级别:

    # semanage login -l
    Login Name      SELinux User         MLS/MCS Range        Service
    __default__     user_u               s0-s0                *
    example_user    user_u               s1                   *
    …
  2. 以 MLS 内的用户身份登录。
  3. 验证用户的安全级别是否正常工作:

    警告

    如果配置不正确,您用于验证的文件不应包含任何敏感信息,并且用户实际上可以访问未经授权的文件。

    1. 验证用户无法读取具有更高级别敏感性的文件。
    2. 验证用户可以写入具有相同敏感级别的文件。
    3. 验证用户可以读取具有较低级别的敏感性的文件。

6.5. 在 MLS 中定义的安全范围内更改用户安全许可的级别

作为 MLS 中的用户,您可以在管理员分配给您的范围内更改当前的安全许可级别。您永远不会超过范围的上限,或将您的级别降到范围的下限以下。例如,您可以修改敏感级别低的文件,而不需要提高其敏感级别。

例如,用户的范围为 s1-s3

  • 您可以将级别切换到 s1s2s3
  • 您可以将范围切换到 s1-s2s2-s3
  • 您不能将范围切换到 s0-s3s1-s4

切换到其他级别会打开一个新的、具有不同安全许可级别的 shell。这意味着,您无法按照降级的相同方式将您的级别恢复到原始的安全许可级别。但是,输入 exit 可以返回到之前的 shell。

先决条件

  • SELinux 策略被设置为 mls
  • SELinux 模式设置为 enforcing(强制)模式。
  • 您可以作为分配了一个 MLS 安全许可级别范围的用户身份登录。

流程

  1. 以用户身份从一个安全终端进行登录。

    安全终端在 /etc/selinux/mls/contexts/securetty_types 文件中定义。默认情况下,控制台是一个安全终端,但 SSH 不是。

  2. 检查当前用户的安全上下文:

    $ id -Z
    user_u:user_r:user_t:s0-s2

    在本例中,该用户被分配给 user_u SELinux 用户、user_r 角色、user_t 类型,以及 MLS 安全范围 s0-s2

  3. 检查当前用户的安全上下文:

    $ id -Z
    user_u:user_r:user_t:s1-s2
  4. 切换到用户安全许可范围内的不同安全许可范围:

    $ newrole -l s1

    您可以切换到任何范围,只要其最大级别低于或等于您被分配的范围的任何范围。输入单级别范围会更改所分配范围的较低限制。例如,输入 newrole -l s1 作为具有 s0-s2 范围的用户,相当于输入 newrole -l s1-s2

验证

  1. 显示当前用户的安全上下文:

    $ id -Z
    user_u:user_r:user_t:s1-s2
  2. 通过终止当前 shell,返回到之前带有原始范围的 shell:

    $ exit

其他资源

6.6. 在 MLS 中增大文件敏感级别

默认情况下,MLS 用户无法增加文件敏感度级别。但是,安全管理员 (secadm_r) 可以更改此默认行为,通过向系统 SELinux 策略添加本地模块 mlsfilewrite 来增加文件的敏感度。然后,分配至策略模块中定义的 SELinux 类型的用户可以通过修改文件来增加文件类别级别。每当用户修改文件时,文件的敏感度级别都会提高用户当前安全范围的值。

安全管理员以分配给 secadm_r 角色的用户身份登录时,可以使用 chcon -l s0 /path/to/file 命令更改文件的安全级别。如需更多信息,请参阅 MLS 中的更改文件敏感度

先决条件

  • SELinux 策略被设置为 mls
  • SELinux 模式设置为 enforcing(强制)模式。
  • 已安装 policycoreutils-python-utils 软件包。
  • mlsfilewrite local 模块安装在 SELinux MLS 策略中。
  • 您以 MLS 中的用户登录,如下:

    • 分配给定义的安全范围。本例演示了一个安全性范围为 s0-s2 的用户。
    • 分配给 mlsfilewrite 模块中定义的同一 SELinux 类型。这个示例需要 (typeattributeset mlsfilewrite (user_t)) 模块。

流程

  1. 可选:显示当前用户的安全上下文:

    $ id -Z
    user_u:user_r:user_t:s0-s2
  2. 将用户的 MLS 安全许可范围的较低级别改为您要分配给该文件的级别:

    $ newrole -l s1-s2
  3. 可选:显示当前用户的安全上下文:

    $ id -Z
    user_u:user_r:user_t:s1-s2
  4. 可选:显示文件的安全上下文:

    $ ls -Z /path/to/file
    user_u:object_r:user_home_t:s0 /path/to/file
  5. 通过修改该文件,将文件的敏感度级别改为用户安全许可的较低级别:

    $ touch /path/to/file
    重要

    如果系统上使用了 restorecon 命令,则分类级别恢复为默认值。

  6. 可选:退出 shell 以返回到用户的前一个安全范围:

    $ exit

验证

  • 显示文件的安全上下文:

    $ ls -Z /path/to/file
    user_u:object_r:user_home_t:s1 /path/to/file

6.7. 在 MLS 中更改文件敏感度

在 MLS SELinux 策略中,用户只能修改自己的敏感度级别的文件。这是为了防止以较低明确的级别向用户公开任何高度敏感信息,同时防止不明确的用户创建高敏感文件。不过,管理员可以手动增加文件的分类,例如要在更高级别处理该文件。

先决条件

  • SELinux 策略设置为 mls
  • SELinux 模式被设置为 enforcing。
  • 您有安全管理权限,这意味着您要分配给其中之一:

    • secadm_r 角色。
    • 如果启用了 sysadm_secadm 模块,进入 sysadm_r 角色。sysadm_secadm 模块默认启用。
  • 已安装 policycoreutils-python-utils 软件包。
  • 分配给任何安全权限级别的用户。如需更多信息,请参阅 MLS 中建立用户清除级别

    在本例中,User1 已有 s1 级别的权限。

  • 分配了安全级别的、您有全访问的文件。

    在本例中,/path/to/file 具有级别 s1 权限。

步骤

  1. 检查该文件的安全级别:

    # ls -lZ /path/to/file
    -rw-r-----. 1 User1 User1 user_u:object_r:user_home_t:s1 0 12. Feb 10:43 /path/to/file
  2. 更改文件的默认安全级别:

    # semanage fcontext -a -r s2 /path/to/file
  3. 强制重新标记文件的 SELinux 上下文:

    # restorecon -F -v /path/to/file
    Relabeled /path/to/file from user_u:object_r:user_home_t:s1 to user_u:object_r:user_home_t:s2

验证

  1. 检查该文件的安全级别:

    # ls -lZ /path/to/file
    -rw-r-----. 1 User1 User1 user_u:object_r:user_home_t:s2 0 12. Feb 10:53 /path/to/file
  2. 可选:验证具有较低级别权限的用户是否无法读取该文件:

    $ cat /path/to/file
    cat: file: Permission denied

其他资源

6.8. 在 MLS 中将系统管理与安全管理分离

默认情况下,sysadm_r 角色具有 secadm_r 角色的权限,这意味着具有 sysadm_r 角色的用户可以管理安全策略。如果需要对安全授权进行更多控制,您可以通过将 Linux 用户分配给 secadm_r 角色并在 SELinux 策略中禁用 sysadm_secadm 模块将系统管理与安全管理分开。

先决条件

  • SELinux 策略被设置为 mls
  • SELinux 模式设置为 enforcing
  • 已安装 policycoreutils-python-utils 软件包。
  • 分配给 secadm_r 角色的 Linux 用户:

    • 该用户被分配给 staff_u SELinux 用户
    • 定义了此用户的密码。
    警告

    确保您可以以用户 身份登录,这将分配给 secadm 角色。如果不能,您可以防止以后修改系统的 SELinux 策略。

步骤

  1. 为用户在 /etc/sudoers.d 目录中创建一个新的 sudoers 文件:

    # visudo -f /etc/sudoers.d/<sec_adm_user>

    为保持 sudoers 文件的组织,请 <sec_adm_user> 替换为将分配给 secadm 角色的 Linux 用户。

  2. /etc/sudoers.d/<sec_adm_user> 文件中添加以下内容:

    <sec_adm_user> ALL=(ALL) TYPE=secadm_t ROLE=secadm_r ALL

    此行授权所有主机上的 <secadmuser> 用户执行所有命令,并默认将用户映射到 secadm SELinux 类型和角色。

  3. 以 < sec_adm_user> 用户身份登录。

    为确保 SELinux 上下文(由 SELinux 用户、角色和类型组成),请使用 ssh、控制台或 xdm进行登录susudo 等其他方法无法更改整个 SELinux 上下文。

  4. 验证用户的安全上下文:

    $ id
    uid=1000(<sec_adm_user>) gid=1000(<sec_adm_user>) groups=1000(<sec_adm_user>) context=staff_u:staff_r:staff_t:s0-s15:c0.c1023
  5. 为 root 用户运行交互式 shell:

    $ sudo -i
    [sudo] password for <sec_adm_user>:
  6. 验证当前用户的安全上下文:

    # id
    uid=0(root) gid=0(root) groups=0(root) context=staff_u:secadm_r:secadm_t:s0-s15:c0.c1023
  7. 从策略中禁用 sysadm_secadm 模块:

    # semodule -d sysadm_secadm
    重要

    使用 semodule -d 命令,而不是使用 semodule -r 命令删除系统策略模块。semodule -r 命令从您的系统存储中删除模块,这意味着无法重新安装 selinux-policy-mls 软件包。

验证

  1. 作为分配给 secadm 角色的用户,并在 root 用户的交互式 shell 中验证您可以访问安全策略数据:

    # seinfo -xt secadm_t
    
    Types: 1
       type secadm_t, can_relabelto_shadow_passwords, (…) userdomain;
  2. 从 root shell 注销:

    # logout
  3. 登出 <sec_adm_user> 用户:

    $ logout
    Connection to localhost closed.
  4. 显示当前安全上下文:

    # id
    uid=0(root) gid=0(root) groups=0(root) context=root:sysadm_r:sysadm_t:s0-s15:c0.c1023
  5. 尝试启用 sysadm_secadm 模块。该命令应该失败:

    # semodule -e sysadm_secadm
    SELinux:  Could not load policy file /etc/selinux/mls/policy/policy.31:  Permission denied
    /sbin/load_policy:  Can't load policy:  Permission denied
    libsemanage.semanage_reload_policy: load_policy returned error code 2. (No such file or directory).
    SELinux:  Could not load policy file /etc/selinux/mls/policy/policy.31:  Permission denied
    /sbin/load_policy:  Can't load policy:  Permission denied
    libsemanage.semanage_reload_policy: load_policy returned error code 2. (No such file or directory).
    semodule:  Failed!
  6. 尝试显示有关 sysadm_t SELinux 类型的详情。该命令应该失败:

    # seinfo -xt sysadm_t
    [Errno 13] Permission denied: '/sys/fs/selinux/policy'

6.9. 在 MLS 中定义安全终端

SELinux 策略会检查用户从中连接的终端类型,并允许运行某些 SELinux 应用程序,例如 newrole,只从安全终端检查。从非安全终端尝试此操作会产生错误:Error: you are not allowed to change levels on a non secure terminal;

/etc/selinux/mls/contexts/securetty_types 文件定义了 MLS 策略的安全终端。

该文件的默认内容:

console_device_t
sysadm_tty_device_t
user_tty_device_t
staff_tty_device_t
auditadm_tty_device_t
secureadm_tty_device_t
警告

将终端类型添加到安全终端列表中,可使您的系统暴露于安全风险。

先决条件

  • SELinux 策略设置为 mls
  • 您从安全的终端进行连接,或者 SELinux 处于 permissive 模式。
  • 您有安全管理权限,这意味着您要分配给其中之一:

    • secadm_r 角色。
    • 如果启用了 sysadm_secadm 模块,进入 sysadm_r 角色。sysadm_secadm 模块默认启用。
  • 已安装 policycoreutils-python-utils 软件包。

流程

  1. 确定当前的终端类型:

    # ls -Z `tty`
    root:object_r:user_devpts_t:s0 /dev/pts/0

    在本例中,user_devpts_t 是当前的终端类型。

  2. /etc/selinux/mls/contexts/securetty_types 文件中的新行中添加相关的 SELinux 类型。
  3. 可选:将 SELinux 切换到 enforcing 模式:

    # setenforce 1

验证

  • 从之前不安全的终端中登录到 /etc/selinux/mls/contexts/securetty_types 文件。

其他资源

  • 您系统上的 securetty_types (5) 手册页

6.10. 允许 MLS 用户在较低级别上编辑文件

默认情况下,MLS 用户无法写入在明确范围内低值下具有敏感等级的文件。如果您的场景需要允许用户在较低级别上编辑文件,可以通过创建本地 SELinux 模块来实现。但是,写入文件会使用户当前范围内的低值提高其敏感度级别。

先决条件

  • SELinux 策略被设置为 mls
  • SELinux 模式设置为 enforcing
  • 已安装 policycoreutils-python-utils 软件包。
  • setools-consoleaudit 软件包进行验证。

流程

  1. 可选:切换到 permissive 模式以方便故障排除。

    # setenforce 0
  2. 使用文本编辑器打开新的 .cil 文件,如 ~/local_mlsfilewrite.cil,并插入以下自定义规则:

    (typeattributeset mlsfilewrite (_staff_t_))

    您可以将 staff_t 替换为不同的 SELinux 类型。通过在此处指定 SELinux 类型,您可以控制哪些 SELinux 角色可以编辑低级别文件。

    要让您的本地模块更好地组织,请在本地 SELinux 策略模块的名称中使用 local_ 前缀。

  3. 安装策略模块:

    # semodule -i ~/local_mlsfilewrite.cil
    注意

    要删除本地策略模块,请使用 semodule -r ~/local_mlsfilewrite。请注意,您必须引用不带 .cil 后缀的模块名称。

  4. 可选:如果您之前切换到 permissive 模式,返回到 enforcing 模式:

    # setenforce 1

验证

  1. 在安装的 SELinux 模块列表中找到本地模块:

    # semodule -lfull | grep "local_mls"
    400 local_mlsfilewrite  cil

    由于本地模块具有优先级 400,所以您也可以使用 semodule -lfull | grep -v ^100 命令列出它们。

  2. 以分配给自定义规则中定义的类型的用户身份登录,例如 staff_t
  3. 尝试写入到具有较低敏感度级别的文件。这会将文件的分类级别增加到用户的安全许可级别。

    重要

    如果配置不正确,您用于验证的文件不应包含任何敏感信息,并且用户实际上可以访问未经授权的文件。

第 7 章 使用多类别安全(MCS)进行数据保密性

您可以使用 MCS 通过分类数据来增强系统数据的机密性,然后授予某些进程和用户对特定类别的访问权限

7.1. 多类别安全性(MCS)

多类别 Security(MCS)是一个访问控制机制,它使用分配给进程和文件的类别。然后,文件只能由分配到相同类别的进程访问。MCS 的目的是维护您系统上的数据保密性。

MCS 类别由 c0c1023 的值定义,但您也可以为每个类别或类别组合定义一个文本标签,如"Personnel"、"ProjectX"或"ProjectX.Personnel"。MCS 转换服务(mcstrans)随后将 category 值替换为系统输入和输出中的相应标签,以便用户可以使用这些标签而不是 category 值。

当用户分配给类别时,他们可以为他们分配的任何类别标记其任何文件。

MCS 适用于一个简单的原则:要访问文件,必须将用户分配给分配给该文件的所有类别。MCS 检查在常规 Linux Discretionary Access Control(DAC)和 SELinux Type Enforcement(TE)规则后应用,因此它只能进一步限制现有的安全配置。

多级别安全中的 MCS

您可以将自己上的 MCS 用作非层次系统,也可以将其与多级别安全(MLS)结合使用,作为分层系统中的非层次结构层。

一个 MLS 中的 MCS 示例是,保密性科研组织,其中文件被分类如下:

表 7.1. 安全级别和类别组合示例

安全级别

类别

未指定

项目 X

项目 Y

项目 Z

未分类

s0

s0:c0

s0:c1

s0:c2

机密

s1

s1:c0

s1:c1

s1:c2

Secret

s2

s2:c0

s2:c1

s2:c2

Top secret

s3

s3:c0

s3:c1

s3:c2

注意

拥有范围 s0:c0.1023 的用户可以访问分配给 s0 级别的所有类别的所有文件,除非访问被其他安全机制禁止,如 DAC 或类型执行策略规则。

文件或进程生成的安全上下文是以下组合:

  • SELinux 用户
  • SELinux 角色
  • SELinux 类型
  • MLS 敏感度级别
  • MCS 类别

例如,在 MLS/MCS 环境中具有访问级别 1 和类别 2 的非授权用户可能具有以下 SELinux 上下文:

user_u:user_r:user_t:s1:c2

7.2. 为数据机密配置多类别安全性

默认情况下,Multi-Category Security (MCS)在 targetedmls SELinux 策略中处于活跃状态,但不会为用户配置。在 targeted 策略中,仅针对以下内容配置 MCS:

  • OpenShift
  • virt
  • sandbox
  • 网络标记
  • containers (container-selinux)

您可以通过创建本地 SELinux 模块并将 user_t SELinux 类型限制在类型强制的情况下,将 MCS 规则配置为分类用户的 MCS 规则。

警告

更改某些文件的类别可能会导致某些服务无法正常运行。如果您并不是相关系统的专家,请联系红帽销售代表并请求咨询服务。

先决条件

  • SELinux 模式设置为 enforcing(强制)模式。
  • SELinux 策略被设置为 targetedmls
  • 已安装 policycoreutils-python-utilssetools-console 软件包。

步骤

  1. 创建一个新文件,例如名为 local_mcs_user.cil

    # vim local_mcs_user.cil
  2. 插入以下规则:

    (typeattributeset mcs_constrained_type (user_t))
  3. 安装策略模块:

    # semodule -i local_mcs_user.cil

验证

  • 对于每个用户域,显示所有组件的更多详情:

    # seinfo -xt user_t
    
    Types: 1
    type user_t, application_domain_type, nsswitch_domain, corenet_unlabeled_type, domain, kernel_system_state_reader, mcs_constrained_type, netlabel_peer_type, privfd, process_user_target, scsi_generic_read, scsi_generic_write, syslog_client_type, pcmcia_typeattr_1, user_usertype, login_userdomain, userdomain, unpriv_userdomain, userdom_home_reader_type, userdom_filetrans_type, xdmhomewriter, x_userdomain, x_domain, dridomain, xdrawable_type, xcolormap_type;

7.3. 在 MCS 中定义类别标签

您可以通过编辑 setrans.conf 文件来管理和维护 MCS 类别标签,或使用 MLS 级别的 MCS 类别组合。在这个文件中,SELinux 在内部敏感度和类别级别及其人类可读标签之间保持映射。

注意

类别标签只让用户更易于使用类别。无论您定义标签或是否定义标签,MCS 的效果都相同。

先决条件

  • SELinux 模式设置为 enforcing
  • SELinux 策略被设置为 targetedmls
  • 已安装 policycoreutils-python-utilsmcstrans 软件包。

步骤

  1. 通过编辑文本编辑器中的 /etc/selinux/<selinuxpolicy>/setrans.conf 文件来修改现有类别或创建新类别。根据您使用的 SELinux 策略,将 <selinuxpolicy> 替换为 targetedmls。例如:

    # vi /etc/selinux/targeted/setrans.conf
  2. 在策略的 setrans.conf 文件中,使用语法 s_<security level>_:c_<category number>_=<category.name> 来定义您的场景所需的类别组合,例如:

    s0:c0=Marketing
    s0:c1=Finance
    s0:c2=Payroll
    s0:c3=Personnel
    • 您可以使用 c0c1023 中的类别号。
    • targeted 策略中,使用 s0 安全级别。
    • mls 策略中,您可以标记各个敏感度级别和类别的组合。
  3. 可选:在 setrans.conf 文件中,您还可以标记 MLS 敏感度级别。
  4. 保存并退出 文件。
  5. 要使更改有效,重启 MCS 翻译服务:

    # systemctl restart mcstrans

验证

  • 显示当前类别:

    # chcat -L

    上面的示例会产生以下输出:

    s0:c0                          Marketing
    s0:c1                          Finance
    s0:c2                          Payroll
    s0:c3                          Personnel
    s0
    s0-s0:c0.c1023                 SystemLow-SystemHigh
    s0:c0.c1023                    SystemHigh

其他资源

  • 您系统上的 setrans.conf (5) 手册页

7.4. 为 MCS 中的用户分配类别

您可以通过为 Linux 用户分配类别来定义用户授权。分配了类别的用户可以访问和修改用户类别子集的文件。用户也可以为他们自己分配到的类别分配文件。

无法将 Linux 用户分配给在为相关 SELinux 用户定义的安全范围之外的类别。

注意

类别访问权限在登录期间分配。因此,在用户再次登录前,用户无法访问新分配的类别。同样,如果您撤销了对类别的访问权限,这仅在用户再次登录后有效。

先决条件

  • SELinux 模式设置为 enforcing
  • SELinux 策略被设置为 targetedmls
  • 已安装 policycoreutils-python-utils 软件包。
  • Linux 用户被分配给 SELinux 受限用户:

    • 非特权用户将分配给 user_u.
    • 特权用户被分配给 staff_u

步骤

  1. 定义 SELinux 用户的安全范围。

    # semanage user -m -rs0:c0,c1-s0:c0.c9 <user_u>

    使用 setrans.conf 文件中的类别号 c0c1023 或 category 标签。如需更多信息,请参阅 MCS 中的定义类别标签

  2. 为 Linux 用户分配 MCS 类别。您只能指定相关 SELinux 用户定义的范围内的范围:

    # semanage login -m -rs0:c1 <Linux.user1>
    注意

    您可以使用 chcat 命令从 Linux 用户添加或删除类别。以下示例添加 <category1> 并从 <Linux.user1><Linux.user2> 中删除 <category2>

    # chcat -l -- +<category1>,-<category2> <Linux.user1>,<Linux.user2>

    在使用 -<category> 语法前,您必须在命令行上指定 --。否则,chcat 命令会错误地将类别删除作为命令选项进行解译。

验证

  • 列出分配给 Linux 用户的类别:

    # chcat -L -l <Linux.user1>,<Linux.user2>
    <Linux.user1>: <category1>,<category2>
    <Linux.user2>: <category1>,<category2>

其他资源

  • 系统中 chcat (8) 手册页

7.5. 为 MCS 中的文件分配类别

您需要具有管理特权才能为用户分配类别。然后用户可以为文件分配类别。要修改文件的类别,用户必须拥有该文件的访问权限。用户只能为为其分配的类别分配一个文件。

注意

系统将类别访问规则与传统的文件访问权限合并。例如,如果具有 bigfoot 类别的用户使用 Discretionary Access Control(DAC)来阻止其他用户对文件的访问,则其他 bigfoot 用户可以访问该文件。分配给所有可用类别的用户仍无法访问整个文件系统。

先决条件

  • SELinux 模式设置为 enforcing
  • SELinux 策略被设置为 targetedmls
  • 已安装 policycoreutils-python-utils 软件包。
  • 对 Linux 用户的访问权限和权限:

  • 访问您要添加到该类别中的文件的访问权限和权限。
  • 为进行验证:对尚未分配给此类别的 Linux 用户访问和权限

步骤

  • 为文件添加类别:

    $ chcat -- +<category1>,+<category2> <path/to/file1>

    使用 setrans.conf 文件中的类别号 c0c1023 或 category 标签。如需更多信息,请参阅 MCS 中的定义类别标签

    您可以使用相同的语法从文件中删除类别:

    $ chcat -- -<category1>,-<category2> <path/to/file1>
    注意

    删除类别时,必须在使用 -<category> 语法前在命令行中指定 --。否则,chcat 命令会错误地将类别删除作为命令选项进行解译。

验证

  1. 显示文件的安全上下文,以验证它具有正确的类别:

    $ ls -lZ <path/to/file>
    -rw-r--r--  <LinuxUser1> <Group1> root:object_r:user_home_t:_<sensitivity>_:_<category>_ <path/to/file>

    文件的特定安全上下文可能有所不同。

  2. 可选:当作为未分配给与该文件相同的类别的 Linux 用户登录时,尝试访问该文件:

    $ cat <path/to/file>
    cat: <path/to/file>: Permission Denied

其他资源

  • 系统中 semanage (8)chcat (8) 手册页

第 8 章 编写自定义 SELinux 策略

要运行受 SELinux 限制的应用程序,您必须编写和使用自定义策略。

8.2. 为自定义应用程序创建并强制 SELinux 策略

您可以通过 SELinux 限制应用程序,来提高主机系统和用户数据的安全性。因为每个应用程序都有特定的要求,因此根据您的用例,为创建限制一个简单守护进程的 SELinux 策略修改这个流程示例。

先决条件

  • selinux-policy-devel 软件包及其依赖项已安装在您的系统上。

步骤

  1. 在本例中,准备一个简单的守护进程,它将打开 /var/log/messages 文件进行写入:

    1. 创建一个新文件,然后在您选择的文本编辑器中打开:

      $ vi mydaemon.c
    2. 插入以下代码:

      #include <unistd.h>
      #include <stdio.h>
      
      FILE *f;
      
      int main(void)
      {
      while(1) {
      f = fopen("/var/log/messages","w");
              sleep(5);
              fclose(f);
          }
      }
    3. 编译文件:

      $ gcc -o mydaemon mydaemon.c
    4. 为您的守护进程创建一个 systemd 单元文件:

      $ vi mydaemon.service
      [Unit]
      Description=Simple testing daemon
      
      [Service]
      Type=simple
      ExecStart=/usr/local/bin/mydaemon
      
      [Install]
      WantedBy=multi-user.target
    5. 安装并启动守护进程:

      # cp mydaemon /usr/local/bin/
      # cp mydaemon.service /usr/lib/systemd/system
      # systemctl start mydaemon
      # systemctl status mydaemon
      ● mydaemon.service - Simple testing daemon
         Loaded: loaded (/usr/lib/systemd/system/mydaemon.service; disabled; vendor preset: disabled)
         Active: active (running) since Sat 2020-05-23 16:56:01 CEST; 19s ago
       Main PID: 4117 (mydaemon)
          Tasks: 1
         Memory: 148.0K
         CGroup: /system.slice/mydaemon.service
                 └─4117 /usr/local/bin/mydaemon
      
      May 23 16:56:01 localhost.localdomain systemd[1]: Started Simple testing daemon.
    6. 检查新守护进程是否没有被 SELinux 限制:

      $ ps -efZ | grep mydaemon
      system_u:system_r:unconfined_service_t:s0 root 4117    1  0 16:56 ?        00:00:00 /usr/local/bin/mydaemon
  2. 为守护进程生成自定义策略:

    $ sepolicy generate --init /usr/local/bin/mydaemon
    Created the following files:
    /home/example.user/mysepol/mydaemon.te # Type Enforcement file
    /home/example.user/mysepol/mydaemon.if # Interface file
    /home/example.user/mysepol/mydaemon.fc # File Contexts file
    /home/example.user/mysepol/mydaemon_selinux.spec # Spec file
    /home/example.user/mysepol/mydaemon.sh # Setup Script
  3. 使用上一命令创建的设置脚本使用新策略模块重建系统策略:

    # ./mydaemon.sh
    Building and Loading Policy
    + make -f /usr/share/selinux/devel/Makefile mydaemon.pp
    Compiling targeted mydaemon module
    Creating targeted mydaemon.pp policy package
    rm tmp/mydaemon.mod.fc tmp/mydaemon.mod
    + /usr/sbin/semodule -i mydaemon.pp
    ...

    请注意,设置脚本使用 restorecon 命令重新标记文件系统的对应部分:

    restorecon -v /usr/local/bin/mydaemon /usr/lib/systemd/system
  4. 重启守护进程,检查它现在被 SELinux 限制:

    # systemctl restart mydaemon
    $ ps -efZ | grep mydaemon
    system_u:system_r:mydaemon_t:s0 root        8150       1  0 17:18 ?        00:00:00 /usr/local/bin/mydaemon
  5. 由于守护进程现在受 SELinux 限制,SELinux 也阻止它访问 /var/log/messages。显示对应的拒绝信息:

    # ausearch -m AVC -ts recent
    ...
    type=AVC msg=audit(1590247112.719:5935): avc:  denied  { open } for  pid=8150 comm="mydaemon" path="/var/log/messages" dev="dm-0" ino=2430831 scontext=system_u:system_r:mydaemon_t:s0 tcontext=unconfined_u:object_r:var_log_t:s0 tclass=file permissive=1
    ...
  6. 您还可以使用 sealert 工具获取更多信息:

    $ sealert -l "*"
    SELinux is preventing mydaemon from open access on the file /var/log/messages.
    
    *****  Plugin catchall (100. confidence) suggests   **************************
    
    If you believe that mydaemon should be allowed open access on the messages file by default.
    Then you should report this as a bug.
    You can generate a local policy module to allow this access.
    Do allow this access for now by executing:
    # ausearch -c 'mydaemon' --raw | audit2allow -M my-mydaemon
    # semodule -X 300 -i my-mydaemon.pp
    
    Additional Information:
    Source Context                system_u:system_r:mydaemon_t:s0
    Target Context                unconfined_u:object_r:var_log_t:s0
    Target Objects                /var/log/messages [ file ]
    Source                        mydaemon
    …
  7. 使用 audit2allow 工具推荐更改:

    $ ausearch -m AVC -ts recent | audit2allow -R
    
    require {
    	type mydaemon_t;
    }
    
    #============= mydaemon_t ==============
    logging_write_generic_logs(mydaemon_t)
  8. 因为 audit2allow 建议的规则在某些情况下可能不正确,所以只使用其输出的一部分来查找对应的策略接口。使用 macro-expander 工具检查 logging_write_generic_logs(mydaemon_t) 宏,以查看宏提供的所有允许规则:

    $ macro-expander "logging_write_generic_logs(mydaemon_t)"
    allow mydaemon_t var_t:dir { getattr search open };
    allow mydaemon_t var_log_t:dir { getattr search open read lock ioctl };
    allow mydaemon_t var_log_t:dir { getattr search open };
    allow mydaemon_t var_log_t:file { open { getattr write append lock ioctl } };
    allow mydaemon_t var_log_t:dir { getattr search open };
    allow mydaemon_t var_log_t:lnk_file { getattr read };
  9. 在这种情况下,您可以使用推荐的接口,因为它只提供对日志文件及其父目录的读写访问。在您的类型强制文件中添加对应的规则:

    $ echo "logging_write_generic_logs(mydaemon_t)" >> mydaemon.te

    另外,您可以添加这个规则而不是使用接口:

    $ echo "allow mydaemon_t var_log_t:file { open write getattr };" >> mydaemon.te
  10. 重新安装策略:

    # ./mydaemon.sh
    Building and Loading Policy
    + make -f /usr/share/selinux/devel/Makefile mydaemon.pp
    Compiling targeted mydaemon module
    Creating targeted mydaemon.pp policy package
    rm tmp/mydaemon.mod.fc tmp/mydaemon.mod
    + /usr/sbin/semodule -i mydaemon.pp
    ...

验证

  1. 检查您的应用程序是否受 SELinux 限制,例如:

    $ ps -efZ | grep mydaemon
    system_u:system_r:mydaemon_t:s0 root        8150       1  0 17:18 ?        00:00:00 /usr/local/bin/mydaemon
  2. 验证您的自定义应用程序不会导致任何 SELinux 拒绝:

    # ausearch -m AVC -ts recent
    <no matches>

其他资源

8.3. 其他资源

第 9 章 为容器创建 SELinux 策略

Red Hat Enterprise Linux 9 使用 udica 软件包提供为容器生成 SELinux 策略的工具。通过 udica,您可以创建一个定制的安全策略来更好地控制容器如何访问主机系统资源,如存储、设备和网络。这可让强化容器部署以避免出现安全问题,并简化了规范合规性的实现和维护。

9.1. udica SELinux 策略生成器介绍

为了简化为自定义容器创建新 SELinux 策略,RHEL 9 提供了 udica 工具。您可以使用此工具基于容器的 JavaScript Object Notation(JSON)文件创建策略,该文件包含 Linux 功能、挂载点和端口定义。因此,该工具将使用检查结果生成的规则与从指定 SELinux 通用中间语言(CIL)块继承的规则合并。

使用 udica 为容器生成 SELinux 策略的过程有三个主要部分:

  1. 以 JSON 格式解析容器规格文件
  2. 根据第一部分的结果查找合适的允许规则
  3. 生成最终 SELinux 策略

在解析阶段,udica 会查找 Linux 功能、网络端口和挂载点。

根据结果,udica 检测到容器需要哪些 Linux 功能,并创建一个允许所有这些功能的 SELinux 规则。如果容器绑定到一个特定端口,udica 使用 SELinux 用户空间库来获取通过检查容器使用的端口的正确 SELinux 标签。

之后,udica 检测到哪些目录被挂载到主机中的容器文件系统名称空间中。

CIL 的块继承功能允许 udica 创建 SELinux 模板,允许规则专注于特定操作,例如:

  • 允许访问主目录
  • 允许访问日志文件
  • 允许访问与 Xserver 的通讯

这些模板称为块,最终 SELinux 策略通过合并这些块来创建。

9.2. 为自定义容器创建和使用 SELinux 策略

要为自定义容器生成 SELinux 安全策略,请按照以下步骤执行。

先决条件

  • 已安装用于管理容器的 podman 工具。如果没有,使用 dnf install podman 命令。
  • 一个自定义 Linux 容器 - 本例中是 ubi8

步骤

  1. 安装 udica 软件包:

    # dnf install -y udica

    或者,安装 container-tools 模块,它提供一组容器软件包,包括 udica

    # dnf module install -y container-tools
  2. 启动 ubi8 容器,它使用只读权限挂载 /home 目录,以及具有读取和写入的权限的 /var/spool 目录。容器会公开端口 21

    # podman run --env container=podman -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it ubi8 bash

    请注意,现在容器使用 container_t SELinux 类型运行。这个类型是 SELinux 策略中所有容器的通用域。针对于您的具体情况,这可能太严格或太宽松。

  3. 打开一个新终端,并输入 podman ps 命令以获取容器的 ID:

    # podman ps
    CONTAINER ID   IMAGE                                   COMMAND   CREATED          STATUS              PORTS   NAMES
    37a3635afb8f   registry.access.redhat.com/ubi8:latest  bash      15 minutes ago   Up 15 minutes ago           heuristic_lewin
  4. 创建容器 JSON 文件,并使用 udica 根据 JSON 文件中的信息创建策略模块:

    # podman inspect 37a3635afb8f > container.json
    # udica -j container.json my_container
    Policy my_container with container id 37a3635afb8f created!
    […]

    或者:

    # podman inspect 37a3635afb8f | udica my_container
    Policy my_container with container id 37a3635afb8f created!
    
    Please load these modules using:
    # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
    
    Restart the container with: "--security-opt label=type:my_container.process" parameter
  5. 如上一步中的 udica 输出所建议,加载策略模块:

    # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
  6. 停止容器并使用 --security-opt label=type:my_container.process 选项再次启动它:

    # podman stop 37a3635afb8f
    # podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it ubi8 bash

验证

  1. 检查容器使用 my_container.process 类型运行:

    # ps -efZ | grep my_container.process
    unconfined_u:system_r:container_runtime_t:s0-s0:c0.c1023 root 2275 434  1 13:49 pts/1 00:00:00 podman run --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -p 21:21 -it ubi8 bash
    system_u:system_r:my_container.process:s0:c270,c963 root 2317 2305  0 13:49 pts/0 00:00:00 bash
  2. 验证 SELinux 现在允许访问 /home/var/spool 挂载点:

    [root@37a3635afb8f /]# cd /home
    [root@37a3635afb8f home]# ls
    username
    [root@37a3635afb8f ~]# cd /var/spool/
    [root@37a3635afb8f spool]# touch test
    [root@37a3635afb8f spool]#
  3. 检查 SELinux 是否只允许绑定到端口 21:

    [root@37a3635afb8f /]# dnf install nmap-ncat
    [root@37a3635afb8f /]# nc -lvp 21
    …
    Ncat: Listening on :::21
    Ncat: Listening on 0.0.0.0:21
    ^C
    [root@37a3635afb8f /]# nc -lvp 80
    …
    Ncat: bind to :::80: Permission denied. QUITTING.

其他资源

第 10 章 在多个系统中部署相同的 SELinux 配置

您可以使用以下方法之一在多个系统上部署验证的 SELinux 配置:

  • 使用 RHEL 系统角色和 Ansible
  • 使用 RHEL web 控制台
  • 在脚本中使用 semanage 导出和导入命令

10.1. selinux RHEL 系统角色简介

RHEL 系统角色是 Ansible 角色和模块的集合,为远程管理多个 RHEL 系统提供一致的配置接口。您可以使用 selinux RHEL 系统角色执行以下操作:

  • 清理与 SELinux 布尔值、文件上下文、端口和登录相关的本地策略修改。
  • 设置 SELinux 策略布尔值、文件上下文、端口和登录。
  • 在指定文件或目录中恢复文件上下文。
  • 管理 SELinux 模块。

rhel-system-roles 软件包安装的 /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml 示例 playbook 演示了如何在 enforcing 模式下设置目标策略。playbook 还应用多个本地策略修改,并在 /tmp/test_dir/ 目录中恢复文件上下文。

其他资源

  • /usr/share/ansible/roles/rhel-system-roles.selinux/README.md file
  • /usr/share/doc/rhel-system-roles/selinux/ directory

10.2. 使用 selinux RHEL 系统角色在多个系统中应用 SELinux 设置

使用 selinux RHEL 系统角色,您可以使用验证的 SELinux 设置准备并应用 Ansible playbook。

先决条件

流程

  1. 准备您的 playbook。您可以从头开始,或修改作为 rhel-system-roles 软件包的一部分安装的示例 playbook:

    # cp /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml <my-selinux-playbook.yml>
    # vi <my-selinux-playbook.yml>
  2. 更改 playbook 的内容,使其适合您的场景。例如,以下部分确保系统安装并启用 selinux-local-1.pp SELinux 模块:

    selinux_modules:
    - { path: "selinux-local-1.pp", priority: "400" }
  3. 保存更改,然后退出文本编辑器。
  4. 验证 playbook 语法:

    $ ansible-playbook <my-selinux-playbook.yml> --syntax-check

    请注意,这个命令只验证语法,不会防止错误但有效的配置。

  5. 运行您的 playbook:

    $ ansible-playbook <my-selinux-playbook.yml>

其他资源

  • /usr/share/ansible/roles/rhel-system-roles.selinux/README.md file
  • /usr/share/doc/rhel-system-roles/selinux/ directory
  • 使用 Ansible 的 SELinux 强化 知识库文章

10.3. 使用 selinux RHEL 系统角色管理端口

您可以使用 selinux RHEL 系统角色在多个系统中自动管理 SELinux 中的端口访问。例如,在将 Apache HTTP 服务器配置为侦听不同端口时,这可能很有用。您可以使用 selinux RHEL 系统角色创建一个 playbook,将 http_port_t SELinux 类型分配给特定的端口号。在受管节点上运行 playbook 后,SELinux 策略中定义的特定服务可以访问此端口。

您可以使用 seport 模块在 SELinux 中自动管理端口访问,这比使用整个角色更快,或者使用 selinux RHEL 系统角色,在对 SELinux 配置进行其他更改时,这更为有用。这个方法等同于 selinux RHEL 系统角色在配置端口时使用 seport 模块。每个方法都与在受管节点上输入 semanage port -a -t http_port_t -p tcp < port_number> 命令的影响相同。

先决条件

  • 您已准备好控制节点和受管节点
  • 以可在受管主机上运行 playbook 的用户登录到控制节点。
  • 用于连接到受管节点的帐户具有 sudo 权限。
  • 可选:要使用 semanage 命令验证端口状态,必须安装 policycoreutils-python-utils 软件包。

流程

  • 要在不进行其他更改的情况下只配置端口号,请使用 seport 模块:

    - name: Allow Apache to listen on tcp port <port_number>
      community.general.seport:
        ports: <port_number>
        proto: tcp
        setype: http_port_t
        state: present

    <port_number > 替换为您要为其分配 http_port_t 类型的端口号。

  • 对于涉及其他 SELinux 自定义的受管节点的更复杂的配置,请使用 selinux RHEL 系统角色。创建一个 playbook 文件,如 ~/playbook.yml,并添加以下内容:

    ---
    - name: Modify SELinux port mapping example
      hosts: all
      vars:
        # Map tcp port <port_number> to the 'http_port_t' SELinux port type
        selinux_ports:
          - ports: <port_number>
            proto: tcp
            setype: http_port_t
            state: present
    
      tasks:
        - name: Include selinux role
          ansible.builtin.include_role:
            name: rhel-system-roles.selinux

    <port_number > 替换为您要为其分配 http_port_t 类型的端口号。

验证

  • 验证端口是否已分配给 http_port_t 类型:

    # semanage port --list | grep http_port_t
    http_port_t                	tcp  	<port_number>, 80, 81, 443, 488, 8008, 8009, 8443, 9000

其他资源

  • /usr/share/ansible/roles/rhel-system-roles.selinux/README.md file
  • /usr/share/doc/rhel-system-roles/selinux/ directory

10.4. 在 web 控制台中创建一个 SELinux 配置 Ansible playbook

在 Web 控制台中,您可以生成一个 shell 脚本或一个 SELinux 配置的 Ansible playbook。如果是 Ansible playbook,您可以在多个系统上方便地应用配置。

先决条件

步骤

  1. 登录到 RHEL 9 web 控制台。

    详情请参阅 登录到 web 控制台

  2. SELinux
  3. View the automation script

    此时会打开一个带有生成的脚本的窗口。您可以在 shell 脚本页和 Ansible playbook 生成选项页之间转换。

    Ansible playbook of your SELinux configuration

  4. Copy to clipboard 按钮选择脚本或 playbook 并应用它。

因此,您有一个可应用到更多机器的自动脚本。

其他资源

10.5. 使用 semanage 将 SELinux 设置传送到另一个系统中

使用以下步骤在基于 RHEL 9 的系统间传输自定义和验证的 SELinux 设置。

先决条件

  • policycoreutils-python-utils 软件包安装在您的系统中。

步骤

  1. 导出验证的 SELinux 设置:

    # semanage export -f ./my-selinux-settings.mod
  2. 使用设置将该文件复制到新系统:

    # scp ./my-selinux-settings.mod new-system-hostname:
  3. 登录新系统:

    $ ssh root@new-system-hostname
  4. 在新系统中导入设置:

    new-system-hostname# semanage import -f ./my-selinux-settings.mod

其他资源

  • 系统中 semanage-export (8)semanage-import (8) 手册页

第 11 章 配置 polyinstantiated 目录

默认情况下,所有程序、服务和用户使用 /tmp/var/tmp 以及主目录进行临时存储。这使得这些目录容易受到基于文件名的竞争条件攻击和信息泄漏的影响。您可以使 /tmp/ /var/tmp / 和主目录实例化,使它们不再在所有用户之间共享,并且每个用户的 /tmp-inst/var/tmp/tmp-inst 单独挂载到 /tmp 和 /var/tmp 目录。

步骤

  1. 在 SELinux 中启用 polyinstantiation:

    # setsebool -P allow_polyinstantiation 1

    您可以通过输入 getsebool allow_polyinstantiation 命令来验证在 SELinux 中是否启用了 polyinstantiation。

  2. 使用所需权限在重启后为数据持久性创建目录结构:

    # mkdir /tmp-inst /var/tmp/tmp-inst --mode 000
  3. 恢复整个安全上下文,包括 SELinux 用户部分:

    # restorecon -Fv /tmp-inst /var/tmp/tmp-inst
    Relabeled /tmp-inst from unconfined_u:object_r:default_t:s0 to system_u:object_r:tmp_t:s0
    Relabeled /var/tmp/tmp-inst from unconfined_u:object_r:tmp_t:s0 to system_u:object_r:tmp_t:s0
  4. 如果您的系统使用 fapolicyd 应用程序控制框架,在 /etc/ fapolicyd /fapolicyd.conf 配置文件中启用 allow_filesystem_mark 选项,允许 fapolicyd 监控底层文件系统上的文件访问事件。

    allow_filesystem_mark = 1
  5. 启用实例化 /tmp/var/tmp/ 和用户主目录:

    重要

    使用 /etc/security/namespace.conf 而不是单独的文件在 /etc/security/namespace.d/ 目录中,因为 pam_namespace_helper 程序不会读取 /etc/security/namespace.d 中的附加文件。

    1. 在具有多级别安全性(MLS)的系统上,取消注释 /etc/security/namespace.conf 文件中的最后三行:

      /tmp     /tmp-inst/   		   level 	 root,adm
      /var/tmp /var/tmp/tmp-inst/    level 	 root,adm
      $HOME    $HOME/$USER.inst/     level
    2. 在没有多级别安全(MLS)的系统上,在 /etc/security/namespace.conf 文件中添加以下行:

      /tmp     /tmp-inst/            user 	 root,adm
      /var/tmp /var/tmp/tmp-inst/    user 	 root,adm
      $HOME    $HOME/$USER.inst/     user
  6. 验证 pam_namespace.so 模块是否已为会话配置:

    $ grep namespace /etc/pam.d/login
    session    required     pam_namespace.so
  7. 可选:启用云用户使用 SSH 密钥访问系统:

    1. 安装 openssh-keycat 软件包。
    2. /etc/ssh/sshd_config.d/ 目录中创建一个包含以下内容的文件:

      AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat
      AuthorizedKeysCommandRunAs root
    3. 通过检查 sshd_config 中的 PubkeyAuthentication 变量设为 yes,验证是否启用了公钥身份验证。默认情况下,Pub keyAuthentication 设置为 yes,即使 sshd_config 中的行被注释掉也是如此。

      $ grep -r PubkeyAuthentication /etc/ssh/
      /etc/ssh/sshd_config:#PubkeyAuthentication yes
  8. 会话包含 system-auth 行后,将所需的 pam_namespace.so unmnt_remnt 条目添加到要应用的每个服务的模块中。例如,在 /etc/pam.d/su/etc/pam.d/sudo/etc/pam.d/ssh 中,以及 /etc/pam.d/sshd

    [...]
    session        include        system-auth
    session        required    pam_namespace.so unmnt_remnt
    [...]

验证

  1. 以非 root 用户身份登录。在配置了 polyinstantiation 之前登录的用户必须注销并登录,然后才能使它们生效。
  2. 检查 /tmp/ 目录是否已挂载到 /tmp-inst/ 下:

    $ findmnt --mountpoint /tmp/
    TARGET SOURCE                 	FSTYPE OPTIONS
    /tmp   /dev/vda1[/tmp-inst/<user>] xfs	rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota

    SOURCE 输出会根据您的环境的不同而有所不同。在 virutal 系统上,它会显示 /dev/vda_<number>_。在裸机系统中,它会显示 /dev/sda_<number>_/dev/nvme*

其他资源

  • /usr/share/doc/pam-docs/txts/README.pam_namespace readme 文件随 pam-docs 软件包安装。

法律通告

Copyright © 2024 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.