最近有很多关于新旧权限提升漏洞的讨论,该漏洞以 Linux 内核中的 Copy-On-Write 内存保护命名为“Dirty COW”。整件事始于大约 11 年前,当时一位内核开发人员留下了一个竞争条件问题:“这是一个古老的错误,实际上我在 11 年前曾尝试修复一次(糟糕地)”。该错误最终于 2016 年 10 月 18 日提交, 并在一天后迅速被报告为 CVE-2016-5195。 不久之后,许多公开的概念验证代码弹出,演示了如何写入只读文件、获得 root 访问权限,甚至跳出容器。
在 Aqua Security Research Labs,我们分析了 Dirty Cow 对集装箱的影响。与其重复解释这个漏洞的工作原理,不如专注于核心的漏洞利用方法,以及它们如何影响容器化环境(如果您想获得“幕后”概述,请从这里开始)。
基本上,此漏洞依赖于内核中的争用条件。竞争发生在两个操作之间:一个操作执行对 COW 内存映射的写入,而另一个操作持续释放该内存。当此操作一遍又一遍地发生时,会发生争用条件,内核可能会意外地将数据写入只读内存映射,而不是先创建私有副本。这就是进程能够将数据写入受保护内存的方式 - 哎哟!
在野外,许多概念验证漏洞利用代码已经开始出现。它们提供了各种形式的权限提升技术,例如修补 SUID
文件、将 shellcode 写入内存中的共享对象等。为了能够执行漏洞利用,进程必须访问其内存。它通过调用 ptrace(需要 SYS_PTRACE
功能)或通过 打开自己的内存(如“文件”)来实现此目的。由于 SYS_PTRACE
方法在容器中的适用性较差(默认情况下,此功能不会添加到容器中),因此我们将重点关注 POC,看看它们在容器化环境中是否构成任何威胁。/proc/self/mem
/proc/self/mem
似乎,所有可用的 POC 都通过写入文件或内存对象来获得 root 权限,而这种写入方式只会导致容器内部的权限提升(一个值得注意的例外是修补 vDSO 的 scumjr POC,这需要 SYS_PTRACE
功能)。但是,这可能会产生误导。为了了解原因,让我们执行几个简单的演示。
将数据写入只读挂载
此漏洞利用的最简单演示是演示如何将数据写入写保护文件。为了更有趣,让我们执行一个 POC
,将数据从容器内部写入只读挂载。主机可以与容器共享文件和目录,但具有给定的限制,例如只读。如果容器能够将数据写入只读文件,则它实际上是“突破”,修改可能敏感的数据,或修改将在主机上获得更多权限的文件。
首先,我们需要检查我们是否有易受攻击的内核(您可以使用此 shell 脚本检查您的内核):
为了演示漏洞利用,我在容器内从非 root 用户 (mike) 运行了这段代码。容器已挂载到包含 “protected” 文件的只读卷:
$ docker run -it -v /root/readonlymnt:/home/mike/readonlymnt:ro dirtyc0wtainer
即使是 root 用户也不应具有对容器中映射的只读卷的写入访问权限(更不用说非 root 用户了)。但是,由于该漏洞,我们看到数据确实已写入位于只读卷中的文件:
所以这很巧妙:我们刚刚看到可以从容器内部操作主机上的数据。
运行具有 User Namespace 的容器
现在,让我们尝试添加另一层安全性:我们将运行一个具有用户命名空间的容器(通过将 标志添加到 Docker 守护进程配置中),并在容器内以非 root 用户的身份运行。当容器使用用户命名空间运行时,容器内的 root 用户将映射到主机上的非 root UID
。这意味着,即使攻击成功获取了容器内的 root 用户,它实际上也是主机上的非特权用户。这听起来更安全,对吧?嗯,是的,但因为我们正在处理内核漏洞,所以答案是“不是真的”。在以下示例中,我们将在 user namespace 中运行一个容器。容器内的用户也将是非 root 用户 (mike): --userns-remap="default"
$ docker run -it -u mike -v /root/readonlymnt:/home/readonlymnt:ro dirtyc0wtainer /bin/bash
当我们列出主机上的进程时,我们看到 shell 不是以 root 身份运行,而是以 uid 101001运行:
在集装箱内部,我们是 mike。Mike 可以读取受保护的数据,但不能写入它:
现在,正如您可能已经猜到的那样,我将再次运行漏洞并写入受保护的文件。当我退出容器并查看文件时,它(毫不奇怪)发生了变化:
结论和建议
总之,当涉及到内核漏洞时,你不能太小心。容器仍然共享相同的内核,一旦被利用,可能会危及其他容器或底层主机。我们看到,一个简单的 POC(不是为了脱离容器)仍然可以修改主机上的数据。
那么管理员应该怎么做呢?修补主机的所有内核始终是一种很好的做法。但是,在现实世界中,这可能并不总是能够做到,或者做得不够快。除了修补之外,确保您的容器在运行时受到保护和监控也至关重要。提供运行时保护的安全产品可用于阻止特定系统调用、限制功能或对某些文件的访问。这些功能允许您以虚拟方式修补容器,从而有效缓解威胁。
原文始发于微信公众号(菜鸟小新):脏牛漏洞:对容器的影响
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论