Docker Security
Reading time: 25 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
基本的 Docker 引擎安全性
Docker 引擎 利用 Linux 内核的 Namespaces 和 Cgroups 来隔离容器,提供基本的安全层。通过 Capabilities dropping、Seccomp 和 SELinux/AppArmor 提供额外的保护,增强容器隔离。一个 auth plugin 可以进一步限制用户操作。
安全访问 Docker 引擎
Docker 引擎可以通过 Unix 套接字本地访问,也可以通过 HTTP 远程访问。对于远程访问,使用 HTTPS 和 TLS 确保机密性、完整性和身份验证是至关重要的。
Docker 引擎默认在 unix:///var/run/docker.sock
上监听。在 Ubuntu 系统上,Docker 的启动选项在 /etc/default/docker
中定义。要启用对 Docker API 和客户端的远程访问,通过添加以下设置来通过 HTTP 套接字暴露 Docker 守护进程:
DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H tcp://192.168.56.101:2376"
sudo service docker restart
然而,由于安全问题,不建议通过 HTTP 暴露 Docker 守护进程。建议使用 HTTPS 来保护连接。保护连接的主要方法有两种:
- 客户端验证服务器的身份。
- 客户端和服务器相互验证对方的身份。
证书用于确认服务器的身份。有关这两种方法的详细示例,请参阅 this guide。
容器镜像的安全性
容器镜像可以存储在私有或公共仓库中。Docker 提供了几种容器镜像的存储选项:
- Docker Hub: Docker 的公共注册服务。
- Docker Registry: 一个开源项目,允许用户托管自己的注册表。
- Docker Trusted Registry: Docker 的商业注册表产品,具有基于角色的用户身份验证和与 LDAP 目录服务的集成。
镜像扫描
容器可能存在 安全漏洞,这可能是由于基础镜像或在基础镜像上安装的软件造成的。Docker 正在进行一个名为 Nautilus 的项目,该项目对容器进行安全扫描并列出漏洞。Nautilus 通过将每个容器镜像层与漏洞库进行比较来识别安全漏洞。
有关更多 information read this。
docker scan
docker scan
命令允许您使用镜像名称或 ID 扫描现有的 Docker 镜像。例如,运行以下命令以扫描 hello-world 镜像:
docker scan hello-world
Testing hello-world...
Organization: docker-desktop-test
Package manager: linux
Project name: docker-image|hello-world
Docker image: hello-world
Licenses: enabled
✓ Tested 0 dependencies for known issues, no vulnerable paths found.
Note that we do not currently have vulnerability data for your image.
trivy -q -f json <container_name>:<tag>
snyk container test <image> --json-file-output=<output file> --severity-threshold=high
clair-scanner -w example-alpine.yaml --ip YOUR_LOCAL_IP alpine:3.5
Docker 镜像签名
Docker 镜像签名确保容器中使用的镜像的安全性和完整性。以下是简要说明:
- Docker 内容信任 利用 Notary 项目,基于更新框架 (TUF),来管理镜像签名。有关更多信息,请参见 Notary 和 TUF。
- 要激活 Docker 内容信任,请设置
export DOCKER_CONTENT_TRUST=1
。此功能在 Docker 版本 1.10 及更高版本中默认关闭。 - 启用此功能后,仅可以下载签名的镜像。初始镜像推送需要为根密钥和标记密钥设置密码,Docker 还支持 Yubikey 以增强安全性。更多详细信息可以在 这里 找到。
- 尝试在启用内容信任的情况下拉取未签名的镜像会导致 "No trust data for latest" 错误。
- 在第一次之后的镜像推送中,Docker 会要求输入存储库密钥的密码以签署镜像。
要备份您的私钥,请使用以下命令:
tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
在切换 Docker 主机时,必须移动根密钥和存储库密钥以维持操作。
容器安全特性
容器安全特性摘要
主要进程隔离特性
在容器化环境中,隔离项目及其进程对于安全和资源管理至关重要。以下是关键概念的简化解释:
命名空间
- 目的:确保进程、网络和文件系统等资源的隔离。特别是在 Docker 中,命名空间使容器的进程与主机和其他容器分开。
unshare
的使用:unshare
命令(或底层系统调用)用于创建新的命名空间,提供额外的隔离层。然而,虽然 Kubernetes 本身并不阻止这一点,但 Docker 确实会。- 限制:创建新命名空间并不允许进程恢复到主机的默认命名空间。要穿透主机命名空间,通常需要访问主机的
/proc
目录,使用nsenter
进行进入。
控制组 (CGroups)
- 功能:主要用于在进程之间分配资源。
- 安全方面:CGroups 本身不提供隔离安全,除了
release_agent
特性,如果配置错误,可能会被利用进行未经授权的访问。
能力丢弃
- 重要性:这是进程隔离的重要安全特性。
- 功能:通过丢弃某些能力来限制根进程可以执行的操作。即使进程以根权限运行,缺乏必要的能力也会阻止其执行特权操作,因为系统调用将因权限不足而失败。
这些是进程丢弃其他能力后的 剩余能力:
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
Seccomp
它在 Docker 中默认启用。它有助于进一步限制进程可以调用的系统调用。
默认的 Docker Seccomp 配置文件可以在 https://github.com/moby/moby/blob/master/profiles/seccomp/default.json 找到。
AppArmor
Docker 有一个可以激活的模板:https://github.com/moby/moby/tree/master/profiles/apparmor
这将允许减少能力、系统调用、对文件和文件夹的访问...
Namespaces
Namespaces 是 Linux 内核的一个特性,它将内核资源进行分区,使得一组进程****看到一组资源,而另一组进程看到不同的资源。该特性通过为一组资源和进程使用相同的命名空间来工作,但这些命名空间指向不同的资源。资源可以存在于多个空间中。
Docker 利用以下 Linux 内核命名空间来实现容器隔离:
- pid namespace
- mount namespace
- network namespace
- ipc namespace
- UTS namespace
有关命名空间的更多信息,请查看以下页面:
cgroups
Linux 内核特性cgroups提供了限制资源如 CPU、内存、IO、网络带宽等的能力,适用于一组进程。Docker 允许使用 cgroup 特性创建容器,从而实现对特定容器的资源控制。
以下是一个用户空间内存限制为 500m,内核内存限制为 50m,CPU 共享为 512,blkio-weight 为 400 的容器。CPU 共享是控制容器 CPU 使用的比例。它的默认值为 1024,范围在 0 到 1024 之间。如果三个容器的 CPU 共享都是 1024,则在 CPU 资源争用的情况下,每个容器最多可以占用 33% 的 CPU。blkio-weight 是控制容器 IO 的比例。它的默认值为 500,范围在 10 到 1000 之间。
docker run -it -m 500M --kernel-memory 50M --cpu-shares 512 --blkio-weight 400 --name ubuntu1 ubuntu bash
要获取容器的 cgroup,您可以执行:
docker run -dt --rm denial sleep 1234 #Run a large sleep inside a Debian container
ps -ef | grep 1234 #Get info about the sleep process
ls -l /proc/<PID>/ns #Get the Group and the namespaces (some may be uniq to the hosts and some may be shred with it)
有关更多信息,请查看:
能力
能力允许对可以允许的根用户能力进行更细粒度的控制。Docker使用Linux内核能力特性来限制可以在容器内执行的操作,无论用户类型如何。
当运行docker容器时,进程会放弃敏感能力,以防止进程逃离隔离。这试图确保进程无法执行敏感操作并逃逸:
Docker中的Seccomp
这是一种安全特性,允许Docker限制可以在容器内使用的系统调用:
Docker中的AppArmor
AppArmor是一个内核增强,用于将容器限制在有限的资源集内,并具有每个程序的配置文件:
Docker中的SELinux
- 标记系统:SELinux为每个进程和文件系统对象分配一个唯一的标签。
- 策略执行:它执行安全策略,定义进程标签可以对系统内其他标签执行的操作。
- 容器进程标签:当容器引擎启动容器进程时,通常会分配一个受限的SELinux标签,通常为
container_t
。 - 容器内文件标记:容器内的文件通常标记为
container_file_t
。 - 策略规则:SELinux策略主要确保具有
container_t
标签的进程只能与标记为container_file_t
的文件进行交互(读取、写入、执行)。
该机制确保即使容器内的进程被攻陷,它也仅限于与具有相应标签的对象进行交互,从而显著限制此类攻陷可能造成的损害。
AuthZ & AuthN
在Docker中,授权插件在安全性中发挥着关键作用,通过决定是否允许或阻止对Docker守护进程的请求来实现。这一决定是通过检查两个关键上下文来做出的:
- 身份验证上下文:这包括有关用户的全面信息,例如他们是谁以及他们如何进行身份验证。
- 命令上下文:这包括与所发出请求相关的所有相关数据。
这些上下文有助于确保只有经过身份验证的用户的合法请求被处理,从而增强Docker操作的安全性。
AuthZ& AuthN - Docker Access Authorization Plugin
来自容器的DoS
如果您没有正确限制容器可以使用的资源,则被攻陷的容器可能会对其运行的主机造成DoS。
- CPU DoS
# stress-ng
sudo apt-get install -y stress-ng && stress-ng --vm 1 --vm-bytes 1G --verify -t 5m
# While loop
docker run -d --name malicious-container -c 512 busybox sh -c 'while true; do :; done'
- 带宽 DoS
nc -lvp 4444 >/dev/null & while true; do cat /dev/urandom | nc <target IP> 4444; done
有趣的 Docker 标志
--privileged 标志
在以下页面中,您可以了解 --privileged
标志意味着什么:
--security-opt
no-new-privileges
如果您正在运行一个容器,攻击者设法以低权限用户身份获得访问权限。如果您有一个 配置错误的 suid 二进制文件,攻击者可能会滥用它并 在容器内提升权限。这可能允许他逃离容器。
启用 no-new-privileges
选项运行容器将 防止这种权限提升。
docker run -it --security-opt=no-new-privileges:true nonewpriv
其他
#You can manually add/drop capabilities with
--cap-add
--cap-drop
# You can manually disable seccomp in docker with
--security-opt seccomp=unconfined
# You can manually disable seccomp in docker with
--security-opt apparmor=unconfined
# You can manually disable selinux in docker with
--security-opt label:disable
对于更多 --security-opt
选项,请查看: https://docs.docker.com/engine/reference/run/#security-configuration
其他安全考虑
管理机密:最佳实践
避免直接在 Docker 镜像中嵌入机密或使用环境变量至关重要,因为这些方法会通过 docker inspect
或 exec
等命令将您的敏感信息暴露给任何可以访问容器的人。
Docker 卷 是一种更安全的替代方案,推荐用于访问敏感信息。它们可以作为内存中的临时文件系统使用,从而降低与 docker inspect
和日志记录相关的风险。然而,根用户和具有 exec
访问权限的用户仍然可能访问这些机密。
Docker secrets 提供了一种更安全的方法来处理敏感信息。对于在镜像构建阶段需要机密的实例,BuildKit 提供了一种高效的解决方案,支持构建时机密,提升构建速度并提供额外功能。
要利用 BuildKit,可以通过三种方式激活:
- 通过环境变量:
export DOCKER_BUILDKIT=1
- 通过命令前缀:
DOCKER_BUILDKIT=1 docker build .
- 通过在 Docker 配置中默认启用:
{ "features": { "buildkit": true } }
,然后重启 Docker。
BuildKit 允许使用 --secret
选项来使用构建时机密,确保这些机密不会包含在镜像构建缓存或最终镜像中,使用命令如下:
docker build --secret my_key=my_value ,src=path/to/my_secret_file .
对于运行中的容器所需的秘密,Docker Compose 和 Kubernetes 提供了强大的解决方案。Docker Compose 在服务定义中使用 secrets
键来指定秘密文件,如 docker-compose.yml
示例所示:
version: "3.7"
services:
my_service:
image: centos:7
entrypoint: "cat /run/secrets/my_secret"
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret_file.txt
此配置允许在使用 Docker Compose 启动服务时使用秘密。
在 Kubernetes 环境中,秘密是原生支持的,并且可以通过像 Helm-Secrets 这样的工具进一步管理。Kubernetes 的基于角色的访问控制 (RBAC) 增强了秘密管理的安全性,类似于 Docker Enterprise。
gVisor
gVisor 是一个应用内核,使用 Go 编写,实施了 Linux 系统表面的相当大一部分。它包括一个名为 runsc
的 Open Container Initiative (OCI) 运行时,提供了 应用程序与主机内核之间的隔离边界。runsc
运行时与 Docker 和 Kubernetes 集成,使得运行沙箱容器变得简单。
GitHub - google/gvisor: Application Kernel for Containers
Kata Containers
Kata Containers 是一个开源社区,致力于构建一个安全的容器运行时,使用轻量级虚拟机,感觉和表现像容器,但提供 使用硬件虚拟化技术的更强工作负载隔离 作为第二道防线。
Kata Containers - Open Source Container Runtime Software | Kata Containers
总结提示
- 不要使用
--privileged
标志或在容器内挂载 Docker socket。 Docker socket 允许生成容器,因此这是完全控制主机的简单方法,例如,通过使用--privileged
标志运行另一个容器。 - 不要在容器内以 root 身份运行。使用 不同用户 和 用户命名空间。 容器内的 root 与主机上的 root 是相同的,除非通过用户命名空间重新映射。它仅受到 Linux 命名空间、能力和 cgroups 的轻微限制。
- 丢弃所有能力 (
--cap-drop=all
),仅启用所需的能力 (--cap-add=...
)。许多工作负载不需要任何能力,添加它们会增加潜在攻击的范围。 - 使用“no-new-privileges”安全选项 以防止进程获得更多权限,例如通过 suid 二进制文件。
- 限制容器可用的资源。 资源限制可以保护机器免受拒绝服务攻击。
- 调整 seccomp、 AppArmor (或 SELinux) 配置文件,以将容器可用的操作和系统调用限制到最低要求。
- 使用 官方 docker 镜像 并要求签名,或基于它们构建自己的镜像。不要继承或使用 后门 镜像。还要将 root 密钥、密码短语存放在安全的地方。Docker 计划通过 UCP 管理密钥。
- 定期 重建 镜像以 应用安全补丁到主机和镜像。
- 明智地管理您的 秘密,使攻击者难以访问它们。
- 如果您 暴露 docker 守护进程,请使用 HTTPS,并进行客户端和服务器身份验证。
- 在您的 Dockerfile 中,优先使用 COPY 而不是 ADD。ADD 会自动提取压缩文件,并可以从 URL 复制文件。COPY 没有这些功能。尽可能避免使用 ADD,以免受到通过远程 URL 和 Zip 文件的攻击。
- 为每个微服务 使用单独的容器
- 不要在容器内放置 ssh,可以使用 “docker exec” 连接到容器。
- 拥有 更小的 容器 镜像
Docker 突破 / 权限提升
如果您 在 docker 容器内 或者您有权访问 docker 组中的用户,您可以尝试 逃逸并提升权限:
Docker Breakout / Privilege Escalation
Docker 身份验证插件绕过
如果您可以访问 docker socket 或者有权访问 docker 组中的用户,但您的操作受到 docker 身份验证插件的限制,请检查您是否可以 绕过它:
AuthZ& AuthN - Docker Access Authorization Plugin
加固 Docker
- 工具 docker-bench-security 是一个脚本,检查在生产中部署 Docker 容器的数十个常见最佳实践。所有测试都是自动化的,并基于 CIS Docker 基准 v1.3.1。
您需要从运行 docker 的主机或具有足够权限的容器中运行该工具。查找 如何在 README 中运行它: https://github.com/docker/docker-bench-security。
参考
- https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/
- https://twitter.com/_fel1x/status/1151487051986087936
- https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-1overview/
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-3engine-access/
- https://sreeninet.wordpress.com/2016/03/06/docker-security-part-4container-image/
- https://en.wikipedia.org/wiki/Linux_namespaces
- https://towardsdatascience.com/top-20-docker-security-tips-81c41dd06f57
- https://www.redhat.com/sysadmin/privileged-flag-container-engines
- https://docs.docker.com/engine/extend/plugins_authorization
- https://towardsdatascience.com/top-20-docker-security-tips-81c41dd06f57
- https://resources.experfy.com/bigdata-cloud/top-20-docker-security-tips/
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。