【问题标题】:Docker(containers) cgroup/namespace setup vs running Dockerfile commands as root?Docker(容器)cgroup /命名空间设置与以root身份运行Dockerfile命令?
【发布时间】:2021-11-13 12:51:12
【问题描述】:

据我了解,docker 设置了所需的 cgroup 和命名空间,因此容器(即容器进程)隔离运行(主机系统上的隔离环境),并且对主机系统的权限和访问权限有限。因此,即使进程在容器中以 root 身份运行,它也不会在主机系统上拥有 root 访问权限。

但是从这篇文章:processes-in-containers-should-not-run-as-root,我看到以 root 身份运行的容器进程仍然可以访问主机系统上只有 root 才能访问的主机文件。

在主机系统上:

root@srv:/root# ls -l
total 4
-rw------- 1 root root 17 Sep 26 20:29 secrets.txt

Dockerfile -

FROM debian:stretch
CMD ["cat", "/tmp/secrets.txt"]

在运行上述 Dockerfile 的对应镜像时,

marc@srv:~$ docker run -v /root/secrets.txt:/tmp/secrets.txt <img>
top secret stuff

如果,top secret stuff 是可读的,怎么可能。那么容器隔离的意义何在。我缺少什么,似乎还有更多我缺少的东西。

(这与我如何使用docker run 有关,默认情况下,所有权限/功能都是基于运行docker run 命令的用户授予容器的。

【问题讨论】:

  • 我想我在重复自己。但我要向我的团队发表声明/演示,我必须 100% 正确。现在我的声明。我有一个保存机密文件的服务器(serverA)。现在用户 (UserA) 有权在此 ServerA 上运行 docker 容器。因此,UserA 现在有一种机制,使用容器通过容器访问主机上的每个文件,而不管 UserA 是否有权访问它。我的理解,来自这个问答。是的。如有错误请指正。

标签: docker cgroups


【解决方案1】:

如果操作员明确授予容器访问权限,则容器只能访问主机文件系统。例如,尝试不带任何docker run -v 选项

docker run        \
  --rm            \  # clean up the container when done
  -u root         \  # explicitly request root user
  busybox         \  # image to run
  cat /etc/shadow    # dumps the _container's_ password file

更一般地说,规则(在没有用户命名空间重新映射的本机 Linux 上)是,如果文件从主机绑定挂载到容器中,如果容器的 numeric 用户或组可以访问它们ID 与文件的所有权和权限相匹配。如果文件在 0600 模式的主机上归 uid 1000 所有,则容器中的 uid 0 或 1000 都可以读取该文件,而不管对应的容器和主机用户名如何。

由此得出的结论是,任何可以运行任何docker run 命令的人都可以轻松地root 整个主机。

docker run             \
  --rm                 \
  -u root              \
  -v /:/host           \  # bind-mount the host filesystem into the container
  busybox              \
  cat /host/etc/shadow    # dumps the host's encrypted password file

容器中的 root 用户进一步受到 Linux 功能的限制:如果不提供特殊的附加 Docker 选项,即使以 root 身份运行,容器也无法更改文件系统挂载、修改网络配置、加载内核模块、重新启动主机,或者做一些其他额外特权的事情。 (而且通常在容器之外做这些事情比给 Docker 额外的权限更好;不要随便运行容器--privileged。)

以非 root 用户身份运行容器通常仍然是更好的做法。用户 ID 不需要特别匹配任何用户 ID,它只需要不为 0(匹配特定主机 uid 不能跨主机移植,不推荐)。容器中的文件一般应该归root所有,所以不会被意外覆盖。

FROM debian

# Create the non-root user
RUN adduser --system --no-create-home nonroot

# Do the normal installation, as root
COPY ...  # no --chown option
RUN ...   # does not run chown either

# Specify the non-root user only for the final container
EXPOSE 12345
USER nonroot
CMD the main container command

如果容器确实需要读取或(尤其是)写入主机文件,请将主机目录绑定挂载到容器中的某些数据特定目录中(不要使用此挂载覆盖应用程序代码)并使用docker run -u用于指定容器需要运行的主机 uid 的选项。用户不需要特别存在于容器的/etc/passwd 文件中。

docker run            \
  -v "$PWD:/app/data" \  # bind-mount the current directory as data
  -u $(id -u)         \  # specify the user ID to use
  ...

【讨论】:

  • 所以它是文件系统可以通过运行容器进程作为 root 给定的卷挂载是可能的。但是在更改各自的文件时,网络配置等也不能更改。
  • 非常出色的答案和解释。谢谢。
  • 大卫,我想我在重复自己。但我要向我的团队发表声明/演示,我必须 100% 正确。现在我的声明。我有一个保存机密文件的服务器(serverA)。现在用户 (UserA) 有权在此 ServerA 上运行 docker 容器。因此,UserA 现在有了一种使用容器的机制,通过使用容器来访问 HOST 上的每个文件,而不管 UserA 是否有权访问它。我的理解,来自这个问答。是的。
  • 当然,userA 可以docker run -v /home/confidential:/files -u root busybox cat /files/seekrit 并在服务器上读取(或写入)任何他们想要的东西。
  • 这样做他们可以给自己主机上的root权限(将自己添加到/etc/sudoers,清除/etc/shadow中的root密码)。他们还可以更直接地启动具有主机网络的特权容器,再次以 root 身份启动,同时禁用 Docker 的控件。
猜你喜欢
  • 2017-05-26
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多