AuthZ& AuthN - Docker Access Authorization Plugin
Docker 的开箱即用 授权 模型是 全有或全无。任何有权限访问 Docker 守护进程的用户都可以 运行任何 Docker 客户端 命令。使用 Docker 的引擎 API 联系守护进程的调用者也是如此。如果您需要 更严格的访问控制,可以创建 授权插件 并将其添加到 Docker 守护进程配置中。使用授权插件,Docker 管理员可以 配置细粒度访问 策略来管理对 Docker 守护进程的访问。
基本架构
Docker Auth 插件是 外部 插件,您可以使用它们来 允许/拒绝 请求 Docker 守护进程的 操作,具体取决于请求的 用户 和 请求的操作。
当通过 CLI 或引擎 API 向 Docker 守护进程 发出 HTTP 请求 时,身份验证 子系统 会将请求传递给已安装的 身份验证 插件。请求包含用户(调用者)和命令上下文。插件 负责决定是否 允许 或 拒绝 请求。
下面的序列图描绘了允许和拒绝的授权流程:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fdocs.docker.com%2Fengine%2Fextend%2Fimages%2Fauthz_allow.png&width=768&dpr=4&quality=100&sign=3a882cd9&sv=1)
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2Fdocs.docker.com%2Fengine%2Fextend%2Fimages%2Fauthz_deny.png&width=768&dpr=4&quality=100&sign=2c94fb8a&sv=1)
发送到插件的每个请求 包括经过身份验证的用户、HTTP 头和请求/响应体。只有 用户名 和 使用的身份验证方法 被传递给插件。最重要的是,不 会传递用户 凭据 或令牌。最后,并非所有请求/响应体都发送 到授权插件。只有那些 Content-Type
为 text/*
或 application/json
的请求/响应体会被发送。
对于可能劫持 HTTP 连接的命令(HTTP Upgrade
),如 exec
,授权插件仅在初始 HTTP 请求时被调用。一旦插件批准命令,后续流程不再应用授权。具体来说,流数据不会传递给授权插件。对于返回分块 HTTP 响应的命令,如 logs
和 events
,仅 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
阅读 README
和 plugin.go
代码以了解其工作原理。
Docker Auth 插件绕过
枚举访问
主要检查的内容是 允许哪些端点 和 允许哪些 HostConfig 值。
要执行此枚举,您可以 使用工具 https://github.com/carlospolop/docker_auth_profiler.
不允许的 run --privileged
run --privileged
最小权限
运行容器并获得特权会话
在这种情况下,系统管理员不允许用户挂载卷并使用 --privileged
标志运行容器或给容器提供任何额外的能力:
然而,用户可以在运行中的容器内创建一个 shell 并赋予其额外的权限:
现在,用户可以使用任何之前讨论过的技术从容器中逃逸,并在主机内部提升权限。
挂载可写文件夹
在这种情况下,系统管理员不允许用户使用 --privileged
标志运行容器或给予容器任何额外的能力,他只允许挂载/tmp
文件夹:
注意,您可能无法挂载文件夹 /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"。 在以下示例中,可以利用此错误配置创建并运行一个挂载主机根目录(/)的容器:
注意在这个例子中,我们将 Binds
参数作为 JSON 的根级键使用,但在 API 中它出现在 HostConfig
键下
HostConfig 中的 Binds
按照与 根中的 Binds 相同的指示,向 Docker API 执行此 请求:
Mounts in root
按照与 Binds in root 相同的指示,向 Docker API 执行此 request:
Mounts in HostConfig
按照与 Binds in root 相同的指示,向 Docker API 执行此 请求:
未检查的 JSON 属性
系统管理员在配置 docker 防火墙时,可能忘记了某个参数的重要属性,例如 API 中的 "Capabilities" 在 "HostConfig" 内。以下示例中,可以利用此错误配置创建并运行具有 SYS_MODULE 能力的容器:
HostConfig
通常是包含 有趣的 权限 的关键,可以用来逃离容器。然而,正如我们之前讨论的,注意在外部使用 Binds 也有效,并且可能允许你绕过限制。
禁用插件
如果 系统管理员 忘记 禁止 禁用 插件 的能力,你可以利用这一点来完全禁用它!
记得在提升权限后重新启用插件,否则docker服务的重启将无效!
Auth Plugin Bypass 文章
Last updated