Docker获取主机系统的root权限

25

当我以普通用户身份运行容器时,我可以映射并修改主机文件系统中由root拥有的目录。这似乎是一个很大的安全漏洞。例如,我可以执行以下操作:

$ docker run -it --rm -v /bin:/tmp/a debian
root@14da9657acc7:/# cd /tmp/a
root@f2547c755c14:/tmp/a# mv df df.orig
root@f2547c755c14:/tmp/a# cp ls df
root@f2547c755c14:/tmp/a# exit

现在我的主机文件系统在键入df命令时将执行ls命令(基本无害的示例)。我不相信这是期望的行为,但它正在我的系统上发生(debian stretch)。docker命令具有普通权限(755,而不是setuid)。

我错过了什么?

也许更好地澄清一下。我目前不感兴趣容器本身可以做什么或能够做什么,也不关心容器内部的根访问权限。

相反,我注意到任何在我的系统上可以运行Docker容器的用户都可以使用它来获得对我的主机系统的根访问权限,并随意读写:实际上给所有用户提供了根访问权限。这显然不是我想要的。如何防止这种情况发生?

3个回答

13

有许多Docker安全功能可用于帮助解决Docker安全问题。其中一个具体的功能是用户命名空间,将有所帮助。

基本上,您需要在关闭Docker守护程序之前在主机上启用用户命名空间:

dockerd --userns-remap=default &

请注意,此操作将禁止容器在特权模式下运行(从安全角度来看是一件好事),并重新启动Docker守护进程(在执行此命令之前应该先停止它)。当您进入Docker容器时,可以将其限制为当前非特权用户:

docker run -it --rm -v /bin:/tmp/a --user UID:GID debian

无论如何,尝试使用默认命令进入Docker容器

docker run -it --rm -v /bin:/tmp/a debian
如果您试图操纵被映射到Docker卷中的主机文件系统(在此情况下为/bin),其中文件和目录的所有者是root,则会收到Permission denied错误。这证明了用户命名空间提供了所需的安全功能。
我建议您查看Docker实验室有关此安全功能的内容,在https://github.com/docker/labs/tree/master/security/userns中进行。我已经完成了所有实验,并在那里打开了问题和PR,以确保实验的完整性,并为它们作证。

3
作为主机系统上的普通用户,我可以运行(例如)标准的 Debian 镜像,这将使我具有对主机的 root 访问权限。实验室说“然而,这也存在潜在的安全风险。” 这话相当保守。它应该说:永远不要以这种方式运行 Docker,因为它会给所有用户提供对主机系统的 root 访问权限。 - Sjaak Dalens
3
谢谢。现在清楚了,我不应该允许任何普通用户运行Docker,而是代替他们来运行。实验室指针也很有用。 - Sjaak Dalens
非管理员用户是否容易覆盖此设置,或者您认为这是一种相当安全的保护安装的方式? - BSUK
@BSUK 需要有 root 权限或者在主机上拥有 Docker 和服务的提升权限的人才能完成此操作。 - Matt Schuchard
在主机上是否有可能阻止用户访问他们无权访问的内容(例如写入绑定挂载的/bin)并仍然允许用户访问他们在主机上拥有的内容(例如写入绑定挂载的主目录)? - Joshua Chia

9
在主机上运行docker命令的访问权限相当于对该主机具有root权限。这是该工具的设计,因为在Linux中挂载文件系统和隔离应用程序所需的功能需要root权限。这里的安全漏洞是任何授予用户运行docker命令的系统管理员都不会信任该主机的root访问权限。因此,向docker组添加用户时必须小心谨慎。

我认为如果正确使用,则Docker仍然可以提高安全性,因为在容器内运行的应用程序受到限制,无法对主机执行的操作。通过明确选项运行容器,例如将根文件系统作为rw卷挂载,直接访问设备或添加允许逃脱名称空间的root能力,才能进行损坏。除了明确创建这些安全漏洞之外,容器内运行的应用程序的访问权限比在容器外运行时要少得多。

如果您仍想尝试锁定具有docker访问权限的用户,则有一些额外的安全功能。用户名空间就是其中之一,它可以防止容器内的root在主机上拥有root访问权限。还有interlock,它允许您限制每个用户可用的命令。


2
这显然是我对概念的误解。谢谢。 - Sjaak Dalens
但是,如果我的工作需要我创建和运行Docker容器,我可以使用docker用户root运行它们并挂载像/etc这样的文件夹到容器中。然后,我就可以使用主机的root权限访问那个文件夹中的文件。我刚刚试过了,在不使用sudo的情况下编辑主机上/etc中的文件。它可以正常工作。我可以直接从Docker容器内部编辑该文件,或者使用普通用户权限在主机上更改权限并进行编辑。我的误解出现在哪里? - Hendrik Wiese
@HendrikWiese dockerd 正在以 root 用户身份运行,因此如果您作为用户直接访问以 root 用户身份运行的守护程序,则具有 root 访问权限。该 API 访问不是普通用户特权。 - BMitch
@HendrikWiese 在主机上运行docker容器的情况需要root访问权限。Docker不是虚拟化平台,它是一个进程容器。此外,“docker”命令不是用户空间命令,它(默认情况下)需要sudo权限。 - Petri Sirkkala

2
您错过了容器默认情况下内部以uid 0运行的事实。所以这是可以预料的。如果您想在容器内更加限制权限,请在Dockerfile中使用USER语句进行构建。这将在运行时将setuid设置为指定的用户,而不是作为root运行。
请注意,该用户的uid不一定可预测,因为它是在您构建的映像内分配的,并且它不一定映射到外部系统上的任何内容。然而,重点是它不会成为root。
有关更多信息,请参阅Dockerfile reference

1
我知道在容器内我以uid 0运行。这很好。但是,如果我将主机系统中的/bin(甚至/)映射到容器中的某个目录,则可以访问和修改主机文件系统并具有root访问权限。因此,我在容器内部执行的命令会以root身份修改外部文件系统。 - Sjaak Dalens
1
@SjaakDalens,我不确定你的目标是什么,但你有各种选择。 将卷映射为只读,构建镜像以使用非特权用户... - Dan Lowe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接