作者:Bryant Hagadorn
链接:http://33h.co/27kdr
随意使用 root 和特权可能会带来不必要的风险。本文展示了特权与 root 运行方式的不同之处以及特权的实际意义。
很多熟悉 Unix 系统的人(例如 macOS、Linux)都习惯于通过使用 sudo
随意提升我们的特权给 root
用户。在调试开发工具或尝试编辑受保护目录中的文件时,经常会发生这种情况,许多人在次尝试之后,执行命令不成功,都会默认使用 sudo
。
--privileged
flag,实际上这与我们随意使用的 sudo 有很大不同,它可能会使应用程序面临不必要的风险。本文将展示这与 root 运行方式有何不同(以及如何避免以 root 用户身份运行),并介绍特权(privileged)的实际含义。作为 root 运行
Docker 允许其在主机操作系统上隔离进程、功能和文件系统,并且实际上,大多数容器默认以 root 身份运行。为了示例,本文将使用 DockerHub 上的三个受欢迎镜像。
$ docker run -it postgres
#whoami
root
#id -u
$ docker run -it couchbase sh
#whoami
root
#id -u
$ docker run -it alpine sh
#whoami
root
#id -u
避免以 root 身份运行
// Dockerfile
FROM microsoft/windowsservercore
# Create Windows user in the container
RUN net user /add patrick
# Set it for subsequent commands
USER patrick
在运行时重写 User ID:
$ docker run -it --user 4000 postgres sh
# whoami
whoami: cannot find name for user ID 4000
# id -u
4000
关于特权
--privileged
flag 将我们之前看到的用户 ID 直接映射到主机的用户 ID,并使其不受限制地访问其选择的任何系统调用。即使 root
在容器内部,在正常操作中,Docker 也会限制容器的 Linux 功能,例如限制 CAP_AUDIT_WRITE,它允许覆盖内核的审计日志,这是容器化工作负载不太需要的功能。# whoami
root # Notice here, we are still root!
# id -u
# hostname
382f1c400bd
# sysctl kernel.hostname=Attacker
sysctl: setting key "kernel.hostname": Read-only file system # Yet we can't do this
$ docker run -it --privileged ubuntu sh
# whoami
root. # Root again
# id -u
# hostname
86c62e9bba5e
# sysctl kernel.hostname=Attacker
kernel.hostname = Attacker # Except now we are privileged
# hostname
Attacker
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: example
spec:
privileged: false # Don't allow privileged pods!
总结
到此为止,我们了解了一些有关 root
和 --privileged
flag 的信息,以及它们与“主机”操作系统的关系。无论我们是否想限制容器的安全性或调试问题,都需要确保应用程序安全。
防御安全性需要深度防御(像洋葱一层一层的保护)并减少攻击面,通过不以 root 身份运行,不以特权身份运行以及添加 SecurityContext 和 PodSecurityPolicies 是实现更高容器安全性的四个主要方面。
END