Systemd 服务加固

Systemd Service Strengthening

简介

在黑客攻击日益频繁的时代,最大限度地减少攻击面至关重要。容器化可能是隔离面向公众服务的最佳方式,但由于多种原因,这并非总是可行。例如,考虑在 systemd 上开发的遗留系统应用程序。这可以充分利用基于 systemd 的操作系统提供的功能,并且可以通过 systemd 单元进行管理,或者可以使用 systemd 计时器自动拉取更新等等。

因此,我们将解释如何提高 systemd 服务的安全性。但首先,我们需要稍微回顾一下。随着最新版本的发布,systemd 实施了一些与安全相关的有趣功能,尤其是沙箱化。在本文中,我们将逐步展示如何使用特定指令加强服务,以及如何使用提供的 systemd 套件检查它们。

调试

Systemd 提供了一个名为 systemd-analyze 的有趣工具。此命令分析一个或多个指定服务的安全性和沙箱设置。该命令检查各种与安全相关的服务设置,根据设置的重要性,为每个设置分配一个数字“暴露级别”值。然后,它通过 0.0…10.0 范围内的估计值计算整个单元的总体暴露级别,这告诉我们服务的安全暴露程度。

Systemd Analyze

 

这使我们能够逐步检查应用于 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 检查安全暴露,我们得到以下结果

Systemd Service Start

现在的安全值是 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

它将所有或部分命名空间限制为服务。该指令接受 cgroupipcnetmntpiduseruts。[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。

加载 Disqus 评论