创建简化后的 SELinux 策略

作者:Irfan Habib

现代 Linux 发行版附带了大量安全特性和工具,其中添加到内核的最重要特性之一是包含了 SELinux。

SELinux 解决了一个最具挑战性的安全问题:如何控制受信任的用户或进程。受信任的用户,例如 *nix 域中的 root 用户,对系统拥有无限且不受限制的访问权限。他们应该拥有这些权限,因为这个帐户本应仅供系统管理员使用;然而,这导致了一个问题。如果 root 帐户本身被黑客入侵,导致黑客完全控制系统,会发生什么?恶意用户不是唯一的问题;安全工具(例如 iptables)的错误配置也可能产生深远的影响。除此之外,想象一下,您部署在服务器上的服务发现了一个安全漏洞,并且没有及时提供补丁。在这种情况下,您的系统是脆弱的。SELinux 通过在 Linux 内核中实现强制访问控制 (MAC) 来保护 Linux 系统免受此类安全问题的影响。SELinux 基于 Flask 安全架构。本文避免讨论 Flask 架构,因为互联网上很容易找到关于它的优秀文档。

为了理解强制访问控制,我们必须了解当前部署的安全模型,称为自主访问控制 (DAC)。在 DAC 系统中,对对象的访问受到基于其分类的限制。这种类型的控制是自主的,因为具有特定访问权限集的主体能够将这些权限传递给另一个主体。例如,您以特定用户身份登录时运行的任何程序都具有与您相同的访问权限。权限由另一个用户(例如 root 用户)设置。

任何特定的权限(读取、写入、执行等等)都可以被认为是一个二维图,用户在一个轴上,对象在另一个轴上。本质上,DAC 系统会根据存储的信息检查提交给它们的凭据的有效性。

如前所述,SELinux 安全模型是强制访问控制,或 MAC。这以不同的方式控制访问。DAC 安全模型是基于身份验证的,而 MAC 系统依赖于授权,不仅是对用户的授权,还包括对系统加载的每个对象的授权。

MAC 系统单独控制对象,并根据安全策略对对象的权限和/或许可做出决策,安全策略可以根据不同的变量定义对象应被授予哪些权限。

一个关于自主访问控制与强制访问控制风格如何影响计算机操作的示例是一个 Python 脚本。如果脚本允许外部实体在 DAC 系统下的计算机系统上插入和执行恶意代码,则恶意代码现在具有与执行它的代码(Python 脚本)相同的访问权限。

MAC 系统可以将特定进程的权限限制为仅限于正常操作所需的资源。Python 脚本可能会创建一个进程(或者可能被禁止),但该进程可能不具有与创建它的进程相同的权限集。因此,MAC 方法被认为是安全的。

SELinux 内部机制简述

在 SELinux 中,安全策略配置在以 m4 语言编写的文本文件中定义。它在安全策略最终确定时编译,并在启动时加载到内存中。只有安全服务器可以对对象的权限做出策略决策。

安全策略的执行由称为对象管理器的组件完成,这些组件接收来自客户端对象的请求,向安全服务器提交查询,并执行最终的决策。

SELinux 安全服务器的实现结合了两种安全范例,称为类型强制 (TE) 和基于角色的访问控制 (RBAC)。

类型强制

类型强制根据请求权限的对象类型做出安全决策。例如,对象类型可以包括常规文件、目录、进程或套接字。类型强制是一种对象标记系统,它与访问映射(从请求权限的对象的域到请求的对象的类型)相结合,返回一个定义对象允许操作的决策。

基于角色的访问控制

基于角色的访问控制根据对象在计算机系统中扮演的角色,向其分配权限。在实践中,这意味着进程的权限将基于其父进程、当时登录的用户以及任何其他变量。

进程、文件系统对象和套接字如何相互通信由安全策略定义。特别是,安全策略管理不同类型和角色如何交互,以及任何特定规则。

目前,SELinux 提供与现有应用程序的二进制兼容性以及与内核模块的源代码兼容性。当前 SELinux 的实现是 x86 特定的。

获取和安装 SELinux

SELinux 现在包含在许多发行版中,即使它没有随主发行版一起提供,通常也可以为流行的发行版提供特定于发行版的软件包。SELinux 的源代码可以从 www.nsa.gov/selinux/code/download0.cfm 获取。

安装 seedit

seedit 是一个用户友好的基于 Webmin 的工具,使管理员能够从 Web 浏览器管理 SELinux 策略。seedit Webmin 界面允许用户在点击式环境中执行他们通常可以通过在 m4 中编写手动脚本来执行的每个操作。

seedit 可从 seedit.sourceforge.net 获取。

安装后,SELinux 策略位于 $SELINUX/(seedit-something)/policy/policy.conf 中(其中 $SELINUX 是您的 SELinux 安装的根目录,通常是 /etc/selinux/)。

让我们熟悉一下 seedit 界面。启动浏览器,将其指向 https://:10000,然后转到系统→SELinux 配置部分。

您将看到六个图标,标记为配置 ACL、定义域转换、定义用户和角色之间的关系、创建新域/角色、删除域/角色和更新配置。

配置 ACL

在这里,您可以定义几乎所有对系统中几乎每个对象的访问控制。这包括允许/禁止对整个目录或单个文件的读取、写入或可执行文件访问,以及允许/禁止访问网络功能。在本节中,您还可以定义特定应用程序可以在其中工作的端口。假设我们将端口 80 分配给 Apache;如果它开始在端口 81 上工作,SELinux 将终止此进程。

IPC 访问控制也可以在本节中定义。您可以定义此特定应用程序可以使用哪种 IPC 机制,以及此特定应用程序可以与哪些应用程序通信。

本节中可以定义的其他访问控制包括各种管理访问控制,例如内核通信权限、SELinux 操作、进程信息检索等等。

定义域转换

在域事务部分,您可以定义哪些进程可以派生当前应用程序——例如,默认情况下,seedit 策略为 MySQL 定义了此域转换:kernel→init→mysqld。这意味着内核可以启动 init,而 init 又可以启动 MySQL 守护程序。如果应用程序有与之关联的守护程序,则应定义域转换,否则守护程序将永远无法启动。

因此,在本节中,用户可以定义域转换、更改现有域转换或完全删除它们。

定义角色和用户之间的关系

角色是对象(如用户)可以在系统上拥有的权限。例如,可能存在一个允许访问系统中所有文件的角色。因此,在本节中,用户可以将角色与系统上的特定用户关联起来。

接下来的两个部分是不言自明的。它们允许您定义新域/角色和删除域/角色。为新应用程序或用户添加访问控制规则时,定义域/角色是第一步。

最后一部分是更新配置部分;它允许用户更新策略并重新编译和加载它。

seedit 附带了大量预定义的策略,涵盖了 Linux 系统中每个流行的服务器/守护程序——从内核到 MySQL 守护程序。

为守护程序应用程序定义新策略

为守护程序定义 SELinux 策略是一个迭代过程。第一步是通过在 seedit Webmin 界面中声明域/角色来向 SELinux“注册”守护程序。这在前面讨论的“添加域/角色”部分中完成。约定是域应以 _t 结尾,角色定义应以 _r 结尾。因此,可能有一个角色,例如 admin_r,以及一个域,例如 mysqld_t。

定义域转换是另一个重要步骤。在这里,您必须允许守护程序的父进程派生相关的守护程序。通常,如果守护程序在启动时激活,则需要定义从 init 到相关守护程序的域转换。

为守护程序定义初始访问控制列表。现在,用户不可能在最初安装守护程序时为其定义详尽的 ACL,通常的做法是定义一个初始 ACL 列表,该列表非常严格。每次应用程序尝试访问对象且不允许这样做时,都会发生访问冲突消息;可以从 /var/log/messages 访问此类消息。考虑到我们正在尝试为其编写规则的守护程序称为 foobar,冲突消息将如下所示

|avc: denied { write } for pid=7279 exe=/usr/bin/foobar comm=ifup
name=dhclient-eth0.conf dev=hda12 ino=57400
scontext=system_u:system_r:foobar_t tcontext=system_u:object_r:etc_t
tclass=file

此冲突表明我们的应用程序尝试对文件 dhclient-eth0.conf 进行写入操作。可以通过授予应用程序对 dhclient-eth0.conf 文件的写入访问权限来消除此冲突。可以通过转到 seedit Webmin 界面的“配置 ACL”部分,在“文件 ACL”部分下,然后浏览到此文件存在的位置,并授予应用程序 foobar 对其的写入访问权限来解决此冲突。

另一个冲突可能如下所示

|avc: denied { create } for pid=7279 exe=/usr/bin/foobar
scontext=root:system_r:foobar_t tcontext=root:system_r:foobar_t\
tclass=udp_socket

此冲突报告应用程序尝试创建 UDP 套接字但被拒绝。要消除此冲突,我们可以简单地将网络功能添加到 foobar_t 域的访问控制中。可以通过转到“配置 ACL”部分,然后在“网络 ACL”部分中,为域 foobar_t 选择“允许网络”来解决此问题。

所有访问冲突都可以在 seedit Webmin 界面的“配置 ACL”部分中解决。

每次策略更新后,通过 seedit Webmin 界面中的“更新策略”选项重新加载它并重新启动守护程序。随着其他冲突的发生,再次更新它,依此类推,直到您几乎没有收到冲突消息为止。

还有其他方法可以借助 audit2allow 工具为应用程序生成访问规则。但是,使用它可能会导致通用规则,从而导致安全问题。但是,您始终可以改进该工具生成的规则。

在创建或更新策略时,请确保已将 SELinux 安装设置为宽容模式。SELinux 有三种模式:强制模式、禁用模式和宽容模式。在强制模式下,所有访问控制都根据定义的策略强制执行。在宽容模式下,策略不强制执行;但是,当发生任何违反策略的情况时,会显示冲突消息。禁用模式完全禁用 SELinux。

Irfan Habib 是巴基斯坦国立科技大学软件工程专业的本科生。多年来,他对自由和开源软件非常感兴趣。

加载 Disqus 评论