runc 工作目录突破 (CVE-2024-21626)

admin 2024年2月8日23:38:53评论16 views字数 2989阅读9分57秒阅读模式

        允许攻击者获得对底层主机操作系统的文件系统访问权限,这可用于获得对主机的特权访问。 

        这会对使用 runc 的基于编排的环境产生影响,例如 Kubernetes。能够将 Pod 部署到 Kubernetes 环境中的攻击者可以利用这一点对底层 Kubernetes 节点执行突破攻击。这对于多租户集群影响更大,因为来自不同租户的 Pod 共享底层节点是很常见的。在这些情况下,Pod 的突破可能允许攻击者访问另一个租户的 Pod。

        还可能影响在容器化环境中托管的运行器中执行的构建管道,并允许攻击者在管道中获得立足点。这可能使攻击者能够获得高特权凭据,从而可以访问生产工作负载或其他敏感环境。 

分析

        runc 是通常用于在 Linux 系统上创建和运行容器的运行时,并且符合开放容器计划 (OCI) 规范。这意味着它创建容器并可以配置各种与容器相关的隔离选项,例如命名空间、cgroup、功能等。 

        容器只是在主机内核上运行的一个进程,利用各种内核功能将容器进程与其他容器和主机本身隔离。其中一种方法是使用容器作为其根文件系统的单独文件系统。这是通过 chroot 实现的。

        这个特定问题是由于文件描述符被泄露造成的,新创建的容器可以使用该文件描述符在主机文件系统命名空间内拥有一个工作目录,如runc 的安全公告中所述。这将位于容器的 chroot 文件系统之外。

        此文件描述符泄漏是通过/proc/self/fd/发生的,其中包含当前进程的文件描述符。runc 创建主机的/sys/fs/cgroup的句柄, /proc/self/fd/中的 runc 可以访问该句柄。确切的文件描述符可能有所不同,但 WithSecure 已成功使用此 CVE 的描述符 7、8 和 9。

        当 runc 创建容器时,攻击者可以指定当前工作目录应该是文件描述符,例如/proc/self/fd/7/。这将使 runc 将当前工作目录设置为主机/sys/fs/cgroup,如果该目录作为文件描述符 7 打开的话。容器内的 PID 1 的工作目录将不在容器的文件系统命名空间内,而是在主机的文件系统命名空间内。攻击者可以利用它来突破容器并获得对底层主机的访问权限,例如通过添加 SSH 密钥,或向其 crontab 添加恶意命令等。如果容器中运行的进程以 UID 0 执行并且没有用户命名空间,攻击者可以以主机的根用户身份执行这些操作,这将导致对主机的特权访问。

下面可以看到使用以下 Dockerfile 的示例:

runc 工作目录突破 (CVE-2024-21626)

构建为测试并运行上述 Dockerfile 后,我们得到以下内容:

runc 工作目录突破 (CVE-2024-21626)

        在测试过程中,我们多次收到第一个错误,大约 4 次尝试后,命令成功。需要注意的一件事表明成功是检索当前目录时出错: 最后一个命令上的 getcwd 错误消息。这表示getcwd 调用失败,考虑到当前工作目录位于容器文件系统命名空间之外,这是有道理的。 

        在主机文件系统上创建一个名为test-host-file 的文件,并枚举容器文件系统确实表明容器可以访问主机文件系统:

runc 工作目录突破 (CVE-2024-21626)

        利用此问题的另一种方法是在现有容器中创建一个新进程。这转换为对 runc 的底层调用,具有设置当前工作目录的相同要求。一个例子如下所示:

runc 工作目录突破 (CVE-2024-21626)

        使用此方法,我们在不同的文件描述符上取得了不同程度的成功。有时 7 会起作用,其他人尝试 7 超过 100 次会失败,我们会切换到另一个文件描述符。在这种情况下,8 有效,我们处于与之前相同的位置,再次如检索当前目录的错误所示:getcwd 错误。 

        切换到 Kubernetes 上下文,主进程不能直接是 shell 命令,因为它没有交互式 tty。可以使用反向 shell 来解决这个问题。更新后的 Dockerfile 如下所示:

runc 工作目录突破 (CVE-2024-21626)

        主要添加的是RUN 命令,它安装 netcat,这是一种用于建立网络连接的常见网络工具。该容器映像已与securelabs/cve-2024-21626一样推送到 docker hub 。

         创建了一个描述部署的 YAML 文件,该文件会将上述映像部署到集群中。如下所示。

runc 工作目录突破 (CVE-2024-21626)

需要注意的是,如果不通过镜像,也可以使用 pod 规范中的workingDir参数来设置工作目录。部署后,我们在列出 pod 时会得到以下信息:

runc 工作目录突破 (CVE-2024-21626)

这是可以预料的,并且与 docker run 相比,描述 pod 时会出现类似的错误。

runc 工作目录突破 (CVE-2024-21626)

        虽然 Kubernetes 将尝试重试部署 Pod,但我们可以强制它更积极地重试,以通过kubectl rollout restart 部署测试来加快尝试速度

        经过多次尝试,WithSecure 成功将文件描述符设置为 9。这是使用withsecurelabs/cve-2024-21626:9 映像。 

runc 工作目录突破 (CVE-2024-21626)

        到目前为止,我们已经演示了通过docker run 和 Kubernetes pod 运行容器来利用此漏洞。但是,容器也是使用docker build创建的。通过在WORKDIR命令之后直接将恶意代码添加到 Dockerfile 中 ,攻击者可以在构建 docker 映像的主机文件系统上执行恶意代码。 

这可以通过下面的 Dockerfile 看到

runc 工作目录突破 (CVE-2024-21626)

        构建此 Dockerfile 时,将创建一个中间映像,其中工作目录设置为/prov/self/fd/7,然后使用该映像创建一个容器以在RUN中运行命令。 

如下所示:

runc 工作目录突破 (CVE-2024-21626)

        可以看出,我们的命令已作为构建的一部分成功执行,并且测试主机文件 也存在,显示这是主机的文件系统。这种方法可用于通过提交恶意更改的 Dockerfile 来破坏 CI/CD 系统,然后由相关 CI/CD 管道的运行者构建这些文件。

检测

        此攻击在创建容器或在容器内生成新进程时利用工作目录。因此,检测尝试将在/proc/self/fd/[0-9]+ 设置为工作目录的位置进行。 

        在 Kubernetes 中,这可以作为 pod 规范的一部分在workingDir字段中设置 ,但这本身并不是一个可靠的机制,因为它也可以在图像配置中设置。查看映像和 Pod 规范以检查工作目录将标记此问题。

        此外,WithSecure 已成功在容器文件系统中创建到/proc/self/fd的符号链接,然后将该符号链接设置为工作目录。这些方法可能更难静态检测,因为攻击者可能会对此方法进行显着的混淆。

        这种攻击可以在运行时检测到。Synk 发布了一个基于 eBPF 的运行时检测器 ,该检测器根据底层系统调用分析工作目录使用的实际路径,并确保未将其设置为文件描述符。

        他们还发布了一个静态分析工具 ,可以分析 Dockerfile 或 docker 镜像。应该注意的是,与运行时检测相比,这可能不太有效,因为可能存在误报或漏报。这是因为它正在处理一组静态的签名和规则,可能无法完全匹配所有情况。 

缓解措施

        Runc 以及依赖于 runc 的扩展软件应修补至 runc 版本 1.1.12 或更高版本。供应商也可能有自己的关于建议操作的建议或安全公告,如果有的话,应遵循这些建议或安全公告。 

原文始发于微信公众号(TtTeam):runc 工作目录突破 (CVE-2024-21626)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月8日23:38:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   runc 工作目录突破 (CVE-2024-21626)https://cn-sec.com/archives/2482443.html

发表评论

匿名网友 填写信息