Kubernetes默认pod配置的巨大攻击面易受严重安全漏洞的影响,其中一些漏洞包括恶意攻击和容器漏洞。笔者认为,防止此类攻击的最有效的工作负载运行时安全措施之一是容器内的逐层进程监控。
这听起来可能是一项艰巨的任务,需要额外的资源,但实际上恰恰相反。在本文中,笔者将介绍如何使用现有的Linux内核安全特性来实现逐层进程监控和防止威胁。
威胁预防和进程监控
Kubernetes中的容器化工作负载由许多层组成。一个有效的运行时安全策略考虑到每个层,并监控每个容器中的进程,也称为进程监控。
进程监控中的威胁检测涉及集成隔离工作负载或控制访问的机制。有了这些控制,你可以有效地防止恶意行为,减少工作负载的攻击面,并限制安全事件的爆炸半径。幸运的是,我们可以使用现有的Kubernetes机制和Linux防御来实现这一点。
内核安全功能
通过使Linux防御更接近容器,我们可以利用现有的Kubernetes机制来监控进程并减少各个层的攻击面。
让我们来看一下seccomp、AppArmour、SELinux和systcl,它们都是内核安全功能,能够控制容器化应用程序所需的系统调用,并为其运行的工作负载虚拟地隔离和定制各个容器。通过使用强制访问控制(MAC)提供对卷或文件系统等资源的访问,这些功能还可以防止容器中断。只需使用这四个功能的默认设置,就可以大大减少集群内的攻击面。
seccomp
seccomp是一个Linux内核特性,它能够在粒度级别过滤容器发出的系统调用。Kubernetes将允许你自动实现容器运行时加载到节点上的seccomp配置文件,包括podman、Docker和CRI-O。
一个简单的seccomp配置文件将包含一个系统调用列表以及每当进行系统调用时的相应操作。启用此功能后,攻击面将减少到允许的系统调用,并禁止使用危险的系统调用。危险的系统调用可能导致内核漏洞、权限升级和容器崩溃。
SELinux
如果你查看CVE-2019-5736、CVE-2016-9962、CVE-2015-3627等,会发现最近的每个容器运行时突破都是一种文件系统突破。你可以通过使用SELinux来缓解这个问题,SELinux可以控制谁可以访问文件系统以及资源(如目录、文件和内存)之间的交互。笔者建议将SELinux配置文件应用于云计算中的工作负载,因为这有助于通过限制主机内核对文件系统的访问来减少攻击面,并允许更好的隔离实践。
SELinux还可以有效地加强传统的Linux自主访问控制(DAC)系统,因为它提供了强制访问控制(MAC)。传统的Linux DAC允许用户更改用户拥有的文件和目录以及处理权限。这同样适用于根用户。
然而,使用SELinux MAC,内核将标记每个OS资源,然后将其存储为扩展文件属性。这些标签用于检查内核内的SELinux策略,以允许交互。通过实现SELinux,容器中的根用户将不再能够访问挂载卷中的主机文件,即使标签不准确。
强制、许可和禁用是SELinux运行的三种模式,它们可以进一步分为目标模式和严格模式。强制和禁用,顾名思义,强制或禁用SELinux策略,而许可则发出警告。你还可以使用Targeted对特定工作负载强制执行策略,或使用Strict对所有进程应用策略。
为了进一步加强SELinux,笔者建议使用多类别安全性(MCS)为资源标记类别。此选项确保用户或进程只能访问标有用户或进程所属类别的文件。启用SELinux后,Docker、CRI-O、podman和其他容器运行时将随机选择MCS标签来运行容器。
除非标记正确,否则容器不会访问主机或Kubernetes卷上的文件。这在资源之间形成了一道重要的屏障,有助于防止与容器泄漏相关的漏洞。
看看下面的例子。使用SELinux配置文件部署了一个pod。除非在主机上标记为s0:c123、c456,否则此pod将无法访问任何主机卷挂载文件。虽然你可以看到整个主机,但文件系统挂载在pod上。
apiVersion: v1 metadata:
name: pod–se–linux–label namespace: default labels:
app: normal–app spec:
containers:
– name: app–container
image: alpine:latest args: [“sleep”, “10000”] securityContext:
seLinuxOptions:
level: “s0:c123,c456”
volumes:
– name: rootfs
hostPath: path: /
SELinux策略很难维护。然而,SELinux策略对于纵深防御战略至关重要。下表列出了可以通过在主机上实现和强制SELinux来防止的容器转义CVE。
AppArmor
与SELinux类似,AppArmor概要文件定义了进程可以访问的内容。以下是AppArmor配置文件的示例:
#include <tunables/global>
/{usr/,}bin/ping flags=(complain) {
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/nameservice>
capability net_raw,
capability setuid,
network inet raw,
/bin/ping mixr,
/etc/modules.conf r,
# Site-specific additions and overrides. See local/README for details.
#include <local/bin.ping>
}
正如你所看到的,这里的ping只有三种功能:net_raw、setuid和对/etc/modules.conf的读取访问。在控制到位的情况下,ping实用程序的攻击面减少了:它不能修改或写入文件系统,包括密钥、设置和二进制文件,也不能加载任何模块。在妥协的情况下,ping实用程序将有一个有限的区域来执行任何恶意活动。
默认情况下,Docker、CRI-O和podman等容器运行时将提供AppArmor配置文件。由于AppArmor灵活且易于维护,笔者建议你为每个微服务设置一个策略。
Sysctl
使用Kubernetessysctl,你可以使用sysctl接口在集群中配置内核参数。Sysctl还允许你修改特定工作负载的内核行为,而不影响集群的其余部分。例如,在处理大量并发连接时,或者如果需要一个特殊的参数集来高效地运行工作负载,可以使用sysctl一起管理容器和资源密集型工作负载。
Sysctl分为两组,安全sysctl和不安全Sysctls。你可以自行决定设置两个组。安全sysctl只影响容器,而不安全sysctls同时影响容器和它们运行的节点。如果需要使用适用于节点的sysctl,笔者建议使用节点关联来调度应用了sysctl的节点上的工作负载。
总结
逐层进程监控是打击安全事件的最有效的解决方案之一,如容器破损和未经授权访问主机资源。虽然你应该始终记住选择适合你的威胁模型的解决方案,但笔者上面提供的解决方案是通过利用现有的Kubernetes机制和Linux防御来启动或改进进程监控的好方法。