25 KiB
Docker安全
{% hint style="success" %}
学习并实践AWS Hacking:HackTricks培训AWS红队专家(ARTE)
学习并实践GCP Hacking: HackTricks培训GCP红队专家(GRTE)
支持HackTricks
- 检查订阅计划!
- 加入 💬 Discord群组 或 电报群组 或 关注我们的 Twitter 🐦 @hacktricks_live.
- 通过向HackTricks和HackTricks Cloud github仓库提交PR来分享黑客技巧。
使用Trickest可以轻松构建和自动化工作流程,使用世界上最先进的社区工具。
立即获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-security" %}
基本Docker引擎安全
Docker引擎利用Linux内核的命名空间和Cgroups来隔离容器,提供基本的安全层。通过Capabilities dropping、Seccomp和SELinux/AppArmor提供额外保护,增强容器隔离。认证插件可以进一步限制用户操作。
安全访问Docker引擎
Docker引擎可以通过Unix套接字本地访问,也可以通过HTTP远程访问。对于远程访问,必须使用HTTPS和TLS来确保机密性、完整性和认证。
默认情况下,Docker引擎在Unix套接字上侦听unix:///var/run/docker.sock
。在Ubuntu系统上,Docker的启动选项定义在/etc/default/docker
中。要启用对Docker API和客户端的远程访问,请添加以下设置:
DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H tcp://192.168.56.101:2376"
sudo service docker restart
然而,由于安全问题,不建议通过HTTP公开Docker守护程序。建议使用HTTPS来保护连接。保护连接的两种主要方法如下:
- 客户端验证服务器的身份。
- 客户端和服务器相互验证彼此的身份。
证书用于确认服务器的身份。有关这两种方法的详细示例,请参考此指南。
容器镜像的安全性
容器镜像可以存储在私有或公共存储库中。Docker为容器镜像提供了几种存储选项:
- Docker Hub:Docker提供的公共注册服务。
- Docker Registry:允许用户托管自己的注册表的开源项目。
- Docker Trusted Registry:Docker的商业注册服务,具有基于角色的用户身份验证和与LDAP目录服务集成的功能。
镜像扫描
容器可能存在安全漏洞,这可能是由于基础镜像或安装在基础镜像之上的软件导致的。Docker正在开发一个名为Nautilus的项目,用于对容器进行安全扫描并列出漏洞。Nautilus通过将每个容器镜像层与漏洞存储库进行比较来识别安全漏洞。
有关更多信息,请阅读此处。
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项目,基于The Update Framework (TUF),来管理镜像签名。有关更多信息,请参阅Notary和TUF。
- 要激活Docker内容信任,请设置
export DOCKER_CONTENT_TRUST=1
。此功能在Docker版本1.10及更高版本中默认处于关闭状态。 - 启用此功能后,只能下载已签名的镜像。初始镜像推送需要为根密钥和标记密钥设置密码,Docker还支持Yubikey以提高安全性。更多详细信息可以在这里找到。
- 在启用内容信任的情况下尝试拉取未签名的镜像会导致“最新版本无信任数据”错误。
- 对于第一次之后的镜像推送,Docker会要求输入存储库密钥的密码以签署镜像。
要备份您的私钥,请使用以下命令:
tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
在切换Docker主机时,需要移动根密钥和存储库密钥以保持运行。
使用Trickest 可以轻松构建和自动化工作流程,利用世界上最先进的社区工具。
立即获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-security" %}
容器安全功能
容器安全功能摘要
主要进程隔离功能
在容器化环境中,隔离项目及其进程对于安全和资源管理至关重要。以下是关键概念的简化解释:
命名空间
- 目的:确保资源(如进程、网络和文件系统)的隔离。特别是在Docker中,命名空间将容器的进程与主机和其他容器分开。
- 使用
unshare
:使用unshare
命令(或底层系统调用)来创建新的命名空间,提供额外的隔离层。然而,尽管Kubernetes本身不会阻止此操作,但Docker会。 - 限制:创建新的命名空间不允许进程恢复到主机的默认命名空间。要穿透主机命名空间,通常需要访问主机的
/proc
目录,并使用nsenter
进行进入。
控制组(CGroups)
- 功能:主要用于在进程之间分配资源。
- 安全方面:CGroups本身并不提供隔离安全性,除了
release_agent
功能,如果配置错误,可能会被利用以获取未经授权的访问权限。
能力降权
- 重要性:这是进程隔离的关键安全功能。
- 功能:通过放弃某些能力,限制根进程可以执行的操作。即使进程以root权限运行,缺乏必要的能力也会阻止其执行特权操作,因为由于权限不足,系统调用将失败。
这些是进程放弃其他能力后的剩余能力:
{% code overflow="wrap" %}
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
{% endcode %}
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
这将允许减少功能、系统调用、对文件和文件夹的访问...
命名空间
命名空间是Linux内核的一个特性,将内核资源分区,使得一组进程看到一组资源,而另一组进程看到不同的资源。该特性通过为一组资源和进程使用相同的命名空间,但这些命名空间指向不同的资源来实现。资源可以存在于多个空间中。
Docker利用以下Linux内核命名空间来实现容器隔离:
- pid命名空间
- mount命名空间
- network命名空间
- ipc命名空间
- UTS命名空间
有关命名空间的更多信息,请查看以下页面:
{% content-ref url="namespaces/" %} namespaces {% endcontent-ref %}
cgroups
Linux内核功能cgroups提供了限制资源(如CPU、内存、IO、网络带宽等)在一组进程中的能力。Docker允许使用cgroup功能创建容器,从而实现对特定容器的资源控制。
以下是一个使用用户空间内存限制为500m、内核内存限制为50m、CPU份额为512、blkioweight为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)
权限
权限允许对root用户可以允许的权限进行更精细的控制。Docker使用Linux内核的权限功能来限制容器内可以执行的操作,无论用户类型如何。
当运行docker容器时,进程会放弃敏感权限,这些权限可以用来逃离隔离。这样可以确保进程无法执行敏感操作并逃脱:
{% content-ref url="../linux-capabilities.md" %} linux-capabilities.md {% endcontent-ref %}
Docker中的Seccomp
这是一个安全功能,允许Docker限制容器内可以使用的系统调用:
{% content-ref url="seccomp.md" %} seccomp.md {% endcontent-ref %}
Docker中的AppArmor
AppArmor是一个内核增强功能,用于将容器限制在一组有限的资源和每个程序的配置文件中。
{% content-ref url="apparmor.md" %} apparmor.md {% endcontent-ref %}
Docker中的SELinux
- 标签系统:SELinux为每个进程和文件系统对象分配一个唯一标签。
- 策略执行:它执行定义了进程标签在系统中可以对其他标签执行什么操作的安全策略。
- 容器进程标签:当容器引擎启动容器进程时,它们通常被分配一个受限SELinux标签,通常是
container_t
。 - 容器内的文件标签:容器内的文件通常被标记为
container_file_t
。 - 策略规则:SELinux策略主要确保具有
container_t
标签的进程只能与标记为container_file_t
的文件交互(读取、写入、执行)。
这种机制确保即使容器内的进程受到损害,也仅限于与具有相应标签的对象交互,从而显著限制了此类妥协可能造成的潜在损害。
{% content-ref url="../selinux.md" %} selinux.md {% endcontent-ref %}
认证和授权
在Docker中,授权插件通过决定是否允许或阻止对Docker守护程序的请求发挥着关键作用。这一决定是通过检查两个关键上下文来做出的:
- 认证上下文:包括有关用户的全面信息,例如他们是谁以及他们如何进行身份验证。
- 命令上下文:包括与正在进行的请求相关的所有相关数据。
这些上下文有助于确保只有经过身份验证的用户的合法请求才会被处理,增强Docker操作的安全性。
{% content-ref url="authz-and-authn-docker-access-authorization-plugin.md" %} authz-and-authn-docker-access-authorization-plugin.md {% endcontent-ref %}
容器中的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
标志意味着什么:
{% content-ref url="docker-privileged.md" %} docker-privileged.md {% endcontent-ref %}
--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
和日志记录相关的风险。然而,root用户和那些具有对容器的exec
访问权限的用户仍然可以访问这些机密信息。
Docker机密提供了一种更安全的处理敏感信息的方法。对于在镜像构建阶段需要机密信息的情况,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启动服务时使用secrets。
在Kubernetes环境中,secrets得到原生支持,并可通过诸如Helm-Secrets等工具进一步管理。Kubernetes的基于角色的访问控制(RBAC)增强了秘钥管理安全性,类似于Docker Enterprise。
gVisor
gVisor是一个用Go编写的应用内核,实现了Linux系统表面的大部分功能。它包括一个名为runsc
的Open Container Initiative (OCI)运行时,提供了应用程序和主机内核之间的隔离边界。runsc
运行时与Docker和Kubernetes集成,使得运行沙盒容器变得简单。
{% embed url="https://github.com/google/gvisor" %}
Kata Containers
Kata Containers是一个开源社区,致力于构建一个安全的容器运行时,使用轻量级虚拟机,感觉和表现类似于容器,但通过硬件虚拟化技术作为第二层防御提供更强大的工作负载隔离。
{% embed url="https://katacontainers.io/" %}
总结提示
- 不要使用
--privileged
标志或在容器内挂载 Docker套接字。 Docker套接字允许生成容器,因此通过使用--privileged
标志运行另一个容器是获取主机完全控制的简单方法。 - 不要在容器内以root身份运行。使用 不同的用户 和 用户命名空间。 容器中的root与主机上的root相同,除非使用用户命名空间重新映射。它仅受到Linux命名空间、功能和cgroups的轻微限制。
- 放弃所有功能 (
--cap-drop=all
),仅启用所需功能 (--cap-add=...
)。许多工作负载不需要任何功能,添加功能会增加潜在攻击的范围。 - 使用“no-new-privileges”安全选项 防止进程获取更多权限,例如通过suid二进制文件。
- 限制容器可用的资源。 资源限制可以保护机器免受拒绝服务攻击。
- 调整 seccomp, AppArmor **(或SELinux)**配置文件,将容器可用的操作和系统调用限制为最低所需。
- 使用 官方Docker镜像 并要求签名,或者基于它们构建自己的镜像。不要继承或使用后门镜像。还要将根密钥、密码存储在安全位置。Docker计划使用UCP管理密钥。
- 定期 重建您的镜像以应用安全补丁到主机和镜像。
- 明智地管理您的secrets,使攻击者难以访问它们。
- 如果暴露Docker守护程序,请使用HTTPS进行客户端和服务器身份验证。
- 在Dockerfile中,优先使用COPY而不是ADD。ADD会自动解压缩文件并可以从URL复制文件。COPY不具备这些功能。尽量避免使用ADD,以免通过远程URL和Zip文件遭受攻击。
- 为每个微服务使用单独的容器
- 不要在容器内放置ssh,“docker exec”可用于ssh到容器。
- 使用更小的容器镜像
Docker越狱/权限提升
如果您在Docker容器内或者拥有docker组中用户的访问权限,您可以尝试越狱和提升权限:
{% content-ref url="docker-breakout-privilege-escalation/" %} docker-breakout-privilege-escalation {% endcontent-ref %}
Docker身份验证插件绕过
如果您可以访问docker套接字或者拥有docker组中用户的访问权限,但您的操作受到docker身份验证插件的限制,请检查是否可以绕过它:
{% content-ref url="authz-and-authn-docker-access-authorization-plugin.md" %} authz-and-authn-docker-access-authorization-plugin.md {% endcontent-ref %}
强化Docker
- 工具docker-bench-security是一个脚本,检查在生产环境中部署Docker容器时的数十个常见最佳实践。这些测试都是自动化的,基于CIS Docker Benchmark 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/
使用Trickest可以轻松构建和自动化工作流程,使用全球最先进的社区工具。
立即获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-security" %}
{% hint style="success" %}
学习和实践AWS黑客技术:HackTricks 培训 AWS 红队专家 (ARTE)
学习和实践GCP黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)
支持 HackTricks
- 检查 订阅计划!
- 加入 💬 Discord 群组 或 电报群组 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库提交 PR 来分享黑客技巧。