Systemd 服务加固

简介
在黑客攻击日益频繁的时代,最大限度地减少攻击面至关重要。容器化可能是隔离面向公众服务的最佳方式,但由于多种原因,这并非总是可行。例如,考虑在 systemd 上开发的遗留系统应用程序。这可以充分利用基于 systemd 的操作系统提供的功能,并且可以通过 systemd 单元进行管理,或者可以使用 systemd 计时器自动拉取更新等等。
因此,我们将解释如何提高 systemd 服务的安全性。但首先,我们需要稍微回顾一下。随着最新版本的发布,systemd 实施了一些与安全相关的有趣功能,尤其是沙箱化。在本文中,我们将逐步展示如何使用特定指令加强服务,以及如何使用提供的 systemd 套件检查它们。
调试
Systemd 提供了一个名为 systemd-analyze 的有趣工具。此命令分析一个或多个指定服务的安全性和沙箱设置。该命令检查各种与安全相关的服务设置,根据设置的重要性,为每个设置分配一个数字“暴露级别”值。然后,它通过 0.0…10.0 范围内的估计值计算整个单元的总体暴露级别,这告诉我们服务的安全暴露程度。

这使我们能够逐步检查应用于 systemd 服务的改进。正如您所看到的,现在有几个服务被标记为 UNSAFE,这可能是因为并非所有应用程序都应用了 systemd 提供的功能。
开始入门
让我们从一个基本示例开始。我们想要创建一个 systemd 单元来启动命令 python3 -m http.server
作为服务
[Unit] Description=Simple Http Server Documentation=https://docs.pythonlang.cn/3/library/http.server.html [Service] Type=simple ExecStart=/usr/bin/python3 -m http.server ExecStop=/bin/kill -9 $MAINPID [Install] WantedBy=multi-user.target
保存文件并将其放置在您的发行版的特定 systemd 目录下。
通过 systemd-analyze security
检查安全暴露,我们得到以下结果

现在的安全值是 9.6/10,并且被标记为 UNSAFE。现在让我们看看如何加强当前服务以使其更安全。
PrivateTmp它在 /tmp/systemd-private-*-[单元名称]-*/tmp
下创建一个文件系统命名空间,而不是共享的 /tmp
或 /var/tmp
。Red Hat Enterprise Linux 发布的许多单元文件都包含此设置,这消除了与 /tmp
中使用的文件的预测和替换相关的整类漏洞。[4]
这是在插入以下指令后服务的外观
[Unit] Description=Simple Http Server Documentation=https://docs.pythonlang.cn/3/library/http.server.html [Service] Type=simple ExecStart=/usr/bin/python3 -m http.server ExecStop=/bin/kill -9 $MAINPID # Sandboxing features PrivateTmp=yes [Install] WantedBy=multi-user.target
这是我们从 systemd-analyze
获得的结果
simplehttp.service 9.2 UNSAFE ?
好的!我们将其从 9.6 降低到 9.2。让我们看看如何使其更安全。
NoNewPrivileges它可以防止服务和相关的子进程提升权限。[4] 添加以下行
NoNewPrivileges=true
下一个结果是
simplehttp.service 9.0 UNSAFE ?RestrictNamespaces
它将所有或部分命名空间限制为服务。该指令接受 cgroup
、ipc
、net
、mnt
、pid
、user
和 uts
。[4]。添加以下行
RestrictNamespaces=uts ipc pid user cgroup
正如您在上面看到的,由于服务需要在网络接口上绑定自身,因此未设置 net
命名空间。将 net
与网络服务隔离将使其无用。
simplehttp.service 8.8 EXPOSED ?最终结果
一旦我们将其他指令添加到服务中,我们就会得到这样的服务
[Unit] Description=Simple Http Server Documentation=https://docs.pythonlang.cn/3/library/http.server.html [Service] Type=simple ExecStart=/usr/bin/python3 -m http.server ExecStop=/bin/kill -9 $MAINPID # Sandboxing features PrivateTmp=yes NoNewPrivileges=true ProtectSystem=strict CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_DAC_READ_SEARCH RestrictNamespaces=uts ipc pid user cgroup ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes PrivateDevices=yes RestrictSUIDSGID=true IPAddressAllow=192.168.1.0/24 [Install] WantedBy=multi-user.target
它最终达到这个结果
simplehttp.service 4.9 OK ?
我们将其从 9.6 降低到 4.9,这是一个非常好的结果。现在整个系统是部分安全的。
结论
我们现在能够提高系统安全性。但请记住,我们并不总是需要应用所有 systemd 指令。这就是为什么我们必须逐步检查它们以确保它们都是有效的。我们也不需要为每个服务都达到较低的值。重要的是使用正确的预防措施来保护我们的系统。
您可以在这里找到一个关于以下文章的 Ansible playbook 演示。这可以帮助您练习 systemd 引入的这项出色功能。
Alessio Greggi 是一位毕业于罗马 Tor Vergata 大学的计算机科学家。他曾担任安全分析师和 DevOps。他主要从事 Shell 脚本、Python、Go 和 Ansible 的工作。您可以通过 LinkedIn 联系 Alessio。