Clue Writeup - Proving Grounds
Created October 8, 2026 • Last updated October 8, 2026 • 4 min read
Clue runs Cassandra Web and FreeSWITCH behind a null-auth SMB share. The Cassandra Web directory traversal (EDB-49362) reads the real event socket password straight off the server and leaks a reused credential from a process command line, giving two separate ways in: FreeSWITCH command execution and SSH. A sudo rule to re-run Cassandra Web as root turns the same traversal bug into a path to an SSH key and root.
Reconnaissance
Nmap
Scan all TCP ports and fingerprint the services.
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 80/tcp open http Apache 2.4.38 (Debian) - 403 Forbidden 139/tcp open netbios-ssn Samba smbd 3.X - 4.X 445/tcp open netbios-ssn Samba 4.9.5-Debian 3000/tcp open http Thin httpd (Cassandra Web) 8021/tcp open freeswitch mod_event_socket
Explain command
| -p- | Scan all 65535 TCP ports. |
| -sC -sV | Run default scripts and probe service versions. |
Port 80 is a 403 dead end. SMB, a Cassandra Web admin UI on 3000, and a FreeSWITCH event socket on 8021 are the interesting services.
SMB Null Session
Check for anonymous SMB access and list shares.
SMB $TARGET_IP 445 CLUE [*] Enumerated shares Share Permissions Remark ----- ----------- ------ print$ Printer Drivers backup READ Backup web directory shares IPC$ IPC Service
Null authentication works and the backup share is readable. Grab everything in it.
getting file \etc\freeswitch\autoload_configs\event_socket.conf.xml <snip>
Searching the dump for secrets turns up the FreeSWITCH event socket config.
<param name="password" value="ClueCon"/>
ClueCon is FreeSWITCH's documented default event socket password, so the backup is stale; the live box almost certainly uses a different one.
Cassandra Web
Browsing to port 3000 confirms Cassandra Web 0.5.0 on Thin httpd, which has a known directory traversal.
Cassandra Web 0.5.0 - Remote File Read | linux/webapps/49362.py
Exploitation
Cassandra Web file read (EDB-49362)
The exploit URL-encodes directory traversal to read arbitrary files through the web UI. Read /etc/passwd first.
root:x:0:0:root:/root:/bin/bash <snip> cassie:x:1000:1000:cassie:/home/cassie:/bin/bash anthony:x:1001:1001:anthony:/home/anthony:/bin/bash freeswitch:x:998:998::/var/lib/freeswitch:/bin/false
Read the live event socket config, which is different from the one in the backup share.
<param name="password" value="$FREESWITCH_PASSWORD"/>
Read Cassandra Web's own process command line, which leaks the credentials it was started with.
/usr/bin/ruby2.5/usr/local/bin/cassandra-web-ucassie-p$CASSIE_PASSWORD
That gives cassie:$CASSIE_PASSWORD for later, and the real FreeSWITCH password for the event socket.
FreeSWITCH RCE (EDB-47799)
Patch the real password into the FreeSWITCH event socket exploit and confirm execution.
uid=998(freeswitch) gid=998(freeswitch) groups=998(freeswitch)
Command execution as freeswitch. The local flag is owned by that user, so read it directly through the same RCE.
<local.txt contents>
Privilege Escalation
Lateral move to cassie
Use the credential leaked from /proc/self/cmdline to SSH in directly.
cassie@clue:~$ id uid=1000(cassie) gid=1000(cassie) groups=1000(cassie)
Check sudo rights.
User cassie may run the following commands on clue:
(ALL) NOPASSWD: /usr/local/bin/cassandra-web
cassie can start Cassandra Web as root with no password, which turns the same traversal bug into a root-owned file read.
Root file read via a root-owned Cassandra Web
Start a second instance bound to localhost, running as root.
[1] Cassandra Web listening on 127.0.0.1:4444
Reach that root-owned instance through the FreeSWITCH RCE, since it only listens on localhost.
"The proof is in another file"
The real flag has a different name; always ls the directory rather than trusting the obvious filename. Cassie's home directory also holds an SSH private key commented anthony@clue.
root@clue:~# id uid=0(root) gid=0(root) groups=0(root)
That key authenticates straight in as root.