hacktricks/linux-hardening/privilege-escalation/docker-security
2023-09-28 19:47:23 +00:00
..
docker-breakout-privilege-escalation Translated ['README.md', 'backdoors/salseo.md', 'cryptography/certificat 2023-09-28 19:47:23 +00:00
namespaces Translated to Chinese 2023-08-03 19:12:22 +00:00
abusing-docker-socket-for-privilege-escalation.md Translated to Chinese 2023-08-03 19:12:22 +00:00
apparmor.md Translated to Chinese 2023-08-03 19:12:22 +00:00
authz-and-authn-docker-access-authorization-plugin.md Translated to Chinese 2023-08-03 19:12:22 +00:00
cgroups.md Translated to Chinese 2023-08-03 19:12:22 +00:00
docker-privileged.md Translated to Chinese 2023-08-03 19:12:22 +00:00
README.md Translated ['README.md', 'backdoors/salseo.md', 'cryptography/certificat 2023-09-28 19:47:23 +00:00
seccomp.md Translated to Chinese 2023-08-03 19:12:22 +00:00
weaponizing-distroless.md Translated to Chinese 2023-08-03 19:12:22 +00:00

Docker安全

☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥


使用Trickest可以轻松构建和自动化工作流程,使用世界上最先进的社区工具。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

基本的Docker引擎安全

Docker引擎负责运行和管理容器。Docker引擎使用Linux内核的命名空间Cgroups功能,提供容器之间的基本隔离。它还使用能力降低SeccompSELinux/AppArmor等功能来实现更好的隔离。

最后,可以使用认证插件限制用户的操作

Docker引擎安全访问

Docker客户端可以通过Unix套接字本地访问Docker引擎也可以通过http远程访问。要进行远程访问需要使用https和TLS,以确保机密性、完整性和身份验证。

默认情况下监听Unix套接字unix:///var/
run/docker.sock在Ubuntu发行版中Docker启动选项在/etc/default/docker中指定。要允许Docker API和客户端远程访问Docker引擎我们需要使用http套接字暴露Docker守护程序。可以通过以下方式完成:

DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H
tcp://192.168.56.101:2376" -> add this to /etc/default/docker
Sudo service docker restart -> Restart Docker daemon

使用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 <ontainer_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内容信任的一些详细信息

  • Docker内容信任是Notary开源项目的一种实现。Notary开源项目基于The Update Framework (TUF)项目
  • 使用export DOCKER_CONTENT_TRUST=1启用Docker内容信任。从Docker版本1.10开始,默认情况下未启用内容信任。
  • 当内容信任被启用时,我们只能拉取已签名的镜像。在推送镜像时,需要输入标记密钥。
  • 当发布者首次使用docker push推送镜像时需要为根密钥和标记密钥输入密码短语。其他密钥将自动生成。
  • Docker还添加了对使用Yubikey的硬件密钥的支持详细信息可在这里找到。

以下是当启用内容信任但镜像未签名时出现的错误信息。

$ docker pull smakam/mybusybox
Using default tag: latest
No trust data for latest

以下输出显示启用签名的容器映像正在推送到Docker Hub。由于这不是第一次推送用户只需输入存储库密钥的密码短语。

$ docker push smakam/mybusybox:v2
The push refers to a repository [docker.io/smakam/mybusybox]
a7022f99b0cc: Layer already exists
5f70bf18a086: Layer already exists
9508eff2c687: Layer already exists
v2: digest: sha256:8509fa814029e1c1baf7696b36f0b273492b87f59554a33589e1bd6283557fc9 size: 2205
Signing and pushing trust metadata
Enter passphrase for repository key with ID 001986b (docker.io/smakam/mybusybox):

需要将根密钥、存储库密钥以及密码短语保存在安全的地方。可以使用以下命令备份私钥:

tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private

当我更改Docker主机时我不得不将根密钥和仓库密钥移动到新主机上进行操作。



使用Trickest轻松构建和自动化由全球最先进的社区工具提供支持的工作流程。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

容器安全功能

容器安全功能摘要

命名空间

命名空间对于将一个项目与其他项目隔离开来非常有用可以隔离进程通信、网络、挂载等。它对于将Docker进程与其他进程甚至/proc文件夹隔离开来非常有用因此它无法滥用其他进程来逃逸。

通过使用二进制文件**unshare(使用unshare系统调用)可以可能"逃逸"或更准确地说是创建新的命名空间**。Docker默认情况下会阻止此操作但Kubernetes不会在撰写本文时
无论如何,这对于创建新的命名空间非常有帮助,但不能返回到主机默认的命名空间(除非您可以访问主机命名空间中的某些/proc,在其中您可以使用**nsenter**进入主机命名空间)。

CGroups

这允许限制资源,并且不会影响进程隔离的安全性(除了release_agent可能被用于逃逸)。

能力降级

我认为这是关于进程隔离安全性最重要的功能之一。这是因为没有这些能力即使进程以root身份运行您也无法执行某些特权操作(因为调用的**syscall**将返回权限错误,因为进程没有所需的能力)。

这些是进程放弃其他能力后的剩余能力

{% 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启用了Seccomp。它有助于进一步限制进程可以调用的系统调用
默认的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内核内存限制为50mCPU份额为512blkioweight为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)

更多信息请查看:

{% content-ref url="cgroups.md" %} cgroups.md {% endcontent-ref %}

权限提升

权限提升允许对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策略定义了关于进程标签在系统上可以做什么的规则。

容器引擎使用单个受限的SELinux标签启动容器进程通常为container_t,然后将容器内部的容器设置为标记为container_file_t。SELinux策略规则基本上表示**container_t进程只能读取/写入/执行标记为container_file_t的文件**。

{% content-ref url="../selinux.md" %} selinux.md {% endcontent-ref %}

AuthZ和AuthN

授权插件根据当前的身份验证上下文和命令上下文来批准或拒绝对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'
  • 带宽拒绝服务攻击

带宽拒绝服务攻击Bandwidth 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

其他

In addition to the security measures mentioned above, there are a few other steps you can take to further harden your Docker environment:

  1. Limit container capabilities: By default, Docker containers have a wide range of capabilities, which can potentially be exploited by attackers. You can restrict these capabilities by using the --cap-drop and --cap-add flags when running containers. Only allow the necessary capabilities for your application to function properly.

  2. Use seccomp profiles: Seccomp (secure computing mode) is a Linux kernel feature that allows you to restrict the system calls that a process can make. Docker supports seccomp profiles, which can be used to further limit the actions that a container can perform. You can create custom seccomp profiles or use pre-defined profiles provided by Docker.

  3. Enable AppArmor or SELinux: AppArmor and SELinux are Linux security modules that provide mandatory access control (MAC) mechanisms. They can be used to enforce additional security policies on Docker containers, restricting their access to system resources. Enable and configure either AppArmor or SELinux based on your Linux distribution.

  4. Monitor container activity: Regularly monitor the activity of your Docker containers to detect any suspicious behavior or unauthorized access attempts. Use tools like Docker logs, Docker events, and container monitoring solutions to keep track of container activity.

  5. Keep Docker up to date: Stay updated with the latest Docker releases and security patches. Docker regularly releases updates to address security vulnerabilities and improve the overall security of the platform. Make sure to regularly update your Docker installation to benefit from these security enhancements.

By implementing these additional security measures, you can further strengthen the security of your Docker environment and reduce the risk of privilege escalation and other security breaches.

#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 inspectexec进入容器的人都可以找到你的机密信息。

Docker卷是更好的选择。它们是Docker文档中推荐的访问敏感信息的方式。你可以将卷用作内存中的临时文件系统。卷可以消除docker inspect和日志记录的风险。然而root用户仍然可以看到机密信息任何可以exec进入容器的人也可以看到。

比卷更好的选择是使用Docker secrets。

如果你只需要将机密信息放在镜像中可以使用BuildKit。BuildKit可以显著缩短构建时间并具有其他很好的功能包括构建时的机密信息支持。

有三种方法可以指定BuildKit后端以便立即使用其功能

  1. 使用export DOCKER_BUILDKIT=1将其设置为环境变量。
  2. buildrun命令前加上DOCKER_BUILDKIT=1
  3. 默认启用BuildKit。在/_etc/docker/daemon.json_中将配置设置为true{ "features": { "buildkit": true } }。然后重新启动Docker。
  4. 然后,您可以使用--secret标志在构建时使用机密信息,如下所示:
docker build --secret my_key=my_value ,src=path/to/my_secret_file .

在您的文件中,将您的秘密指定为键值对。

这些秘密将从镜像构建缓存中排除,并且不会出现在最终镜像中。

如果您需要在运行的容器中使用您的秘密而不仅仅是在构建镜像时请使用Docker Compose或Kubernetes。

使用Docker Compose将秘密键值对添加到服务中并指定秘密文件。感谢Stack Exchange答案提供的Docker Compose秘密提示下面的示例是根据该答案进行调整的。

带有秘密的示例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 up --build my_service启动Compose。

如果您正在使用Kubernetes,它支持密钥管理。Helm-Secrets可以帮助简化Kubernetes中的密钥管理。此外Kubernetes和Docker Enterprise都支持基于角色的访问控制RBAC。RBAC使得密钥管理对团队来说更易管理和更安全。

gVisor

gVisor是一个用Go编写的应用程序内核它实现了Linux系统的大部分功能。它包括一个名为runscOpen 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二进制文件。
  • 限制容器可用的资源**。**资源限制可以保护机器免受拒绝服务攻击。
  • 调整seccompAppArmor**或SELinux**配置文件,将容器可用的操作和系统调用限制为最小。
  • 使用官方的Docker镜像并要求签名,或者基于官方镜像构建自己的镜像。不要继承或使用后门镜像。还要将根密钥和密码短语存放在安全的地方。Docker计划使用UCP来管理密钥。
  • 定期重新构建镜像以应用安全补丁到主机和镜像上
  • 明智地管理您的密钥,使攻击者难以访问它们。
  • 如果公开了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

参考资料

使用[**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks)轻松构建和自动化由全球**最先进**的社区工具提供支持的工作流程。 立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥