July 10, 2026
The Hackers Labs Writeup — ScapeRoom (Spanish)
A continuación, describo la guía de resolución del laboratorio de The Hackers Labs denominado “ScapeRoom”.

By David Prieto Montero (a.k.a Pyth0nK1d)
15 min read
Este laboratorio está catalogado con la dificultad "Avanzado" y sus autores son "oskitaar" y "oscaar90" (Medium: Oscaarsanchez).
ATENCIÓN
Las herramientas y técnicas utilizadas en la resolución de este laboratorio han sido ejecutadas en un entorno controlado. El autor de esta publicación no se hace responsable del mal uso que se haga de estas, ya que el objetivo final de esta publicación es transmitir conocimientos con fines éticos y educativos.
Resumen de contenido sobre este laboratorio
Tags: Contraseña débil ,Divulgación de información, Precarga de librerías dinámicas (Shared Library Preloading), Seguridad por oscuridad
Antes de comenzar, se indica un resumen de las explotaciones exitosas llevadas a cabo para completar este laboratorio:
- Investigación, análisis y detección de una cadena de credenciales empezando desde un punto de vista anónimo hasta obtener acceso administrativo a la web expuesta. En esta se detectan credenciales en texto plano que permiten realizar el acceso inicial al sistema objetivo a través del servicio SSH como el usuario
pepito. - Obtención de credenciales en texto plano de una librería dinámica presente en el sistema, permitiendo escalar privilegios al usuario
root. - Investigación adicional realizada entorno al reto planteado en este laboratorio para entender en mayor profundidad su funcionamiento y las limitaciones impuestas.
Reconocimiento inicial
Se inicia el reconocimiento mediante un ping a la máquina. Esto se hace por un lado para detectar que la máquina se encuentra accesible y por otro lado para poder detectar el sistema operativo mediante el TTL asignado.
ping -c 1 10.0.70.6ping -c 1 10.0.70.6
Se puede comprobar que el TTL asignado es 64, indicando que la máquina está accesible directamente sin ningún nodo intermediario y por otro lado que el sistema subyacente es GNU/Linux.
Una vez hecho esto, se realiza un reconocimiento de los servicios disponibles en dos fases. En la primera, se realiza un escaneo de todos los puertos TCP usando nmap para detectar en primera instancia cuales de ellos son accesibles (open), utilizando un escaneo TCP SYN.
sudo nmap -sS -p- --min-rate 1000 -n -Pn 10.0.70.6 -oN allPortssudo nmap -sS -p- --min-rate 1000 -n -Pn 10.0.70.6 -oN allPorts
En la segunda, se realiza un reconocimiento básico de los servicios subyacentes también mediante el uso de nmap. Esta vez, realizando dicha tarea de reconocimiento únicamente en los puertos detectados como abiertos.
nmap -sCV -p 22,80,3306,33060 -n -Pn 10.0.70.6 -oN servicesnmap -sCV -p 22,80,3306,33060 -n -Pn 10.0.70.6 -oN services
En este caso, se omite el escaneo de puertos UDP, ya que para esta máquina en particular no tiene ningún servicio relevante para llevar a cabo el ejercicio.
Acceso inicial (pepito)
En este caso se detecta que hay cuatro puertos abiertos:
- Puerto 22 (servicio SSH, OpenSSH)
- Puerto 80 (servicio HTTP, Apache httpd 2.4.41)
- Puerto 3306 (servicio MySQL, MySQL 8.0.40)
- Puerto 33060 (servicio MySQLX, MySQL X protocol listener)
Además, gracias a la detección del servicio, se detecta que el sistema subyacente es Ubuntu.
Tras revisar el puerto 80, se detecta una página que muestra un monitor de lecturas de sensores.
URL -> http://10.0.70.6URL -> http://10.0.70.6
Al revisar el código fuente se detecta un texto codificado en Base64.
URL -> view-source:http://10.0.70.6URL -> view-source:http://10.0.70.6
Tras descodificarlo muestra una pista sobre un posible recurso oculto que hay que encontrar.
echo 'QSB2ZWNlcywgbG8gbcOhcyBvYnZpbyBlcyBsbyBxdWUgc2UgcGFzYSBwb3IgYWx0by4gVHUgw7puaWNhIHNhbGlkYSBlcyB2ZXIgbG8gcXVlIG90cm9zIG5vIHZlbi4gRWwgdGllbXBvIGNvcnJlIHkgY2FkYSBwaXN0YSBlcyB1bmEgcGllemEgY2xhdmUgZGVsIHJvbXBlY2FiZXphcy4K' | base64 -d
...
A veces, lo más obvio es lo que se pasa por alto. Tu única salida es ver lo que otros no ven. El tiempo corre y cada pista es una pieza clave del rompecabezas.echo 'QSB2ZWNlcywgbG8gbcOhcyBvYnZpbyBlcyBsbyBxdWUgc2UgcGFzYSBwb3IgYWx0by4gVHUgw7puaWNhIHNhbGlkYSBlcyB2ZXIgbG8gcXVlIG90cm9zIG5vIHZlbi4gRWwgdGllbXBvIGNvcnJlIHkgY2FkYSBwaXN0YSBlcyB1bmEgcGllemEgY2xhdmUgZGVsIHJvbXBlY2FiZXphcy4K' | base64 -d
...
A veces, lo más obvio es lo que se pasa por alto. Tu única salida es ver lo que otros no ven. El tiempo corre y cada pista es una pieza clave del rompecabezas.
Al escanear la web en busca de nuevos recursos, se detecta un nuevo directorio denominado "administracion".
gobuster dir -u http://10.0.70.6 -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -t 50 -x php,html,txt,zipgobuster dir -u http://10.0.70.6 -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -t 50 -x php,html,txt,zip
Sin embargo, al acceder devuelve un código de estado 403 — Prohibido.
URL -> http://10.0.70.6/administracion/ -> 403 - ProhibidoURL -> http://10.0.70.6/administracion/ -> 403 - Prohibido
Al escanear nuevamente la web bajo este directorio, resulta en detectar un nuevo recurso.
gobuster dir -u http://10.0.70.6/administracion -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -t 50 -x php,html,txt,zipgobuster dir -u http://10.0.70.6/administracion -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -t 50 -x php,html,txt,zip
Al acceder este muestra un página que contiene un formulario de login.
URL -> http://10.0.70.6/administracion/login.phpURL -> http://10.0.70.6/administracion/login.php
Al introducir unas credenciales cualquiera, este muestra un mensaje de error un tanto peculiar.
Usuario: test
Contraseña: test
...
Error: La tabla de login está vacía o el usuario no existe.Usuario: test
Contraseña: test
...
Error: La tabla de login está vacía o el usuario no existe.
Tras revisar con Burp Suite la respuesta obtenida al interactuar con esta funcionalidad, se detectan una serie de cabeceras personalizadas que muestran una pista que apunta a un dominio en particular.
Para hacer que resuelva este dominio, es necesario añadir dicho dominio junto a la IP correspondiente en el archivo /etc/hosts de la máquina local, ya que parece estar aplicando virtual hosting basado en nombre para servirlo.
sudo mousepad /etc/hosts
10.0.70.6 sensores.thl (añadir esta linea y guardar los cambios)sudo mousepad /etc/hosts
10.0.70.6 sensores.thl (añadir esta linea y guardar los cambios)Al intentar resolverlo con el dominio, se puede comprobar que muestra exactamente la misma página.
URL -> http://sensores.thlURL -> http://sensores.thl
Por ello, se prueba a enumerar subdominios utilizando la herramienta "gobuster", con el cual se encuentra un subdominio: info.sensores.thl
gobuster vhost -u http://sensores.thl -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt --append-domain -rgobuster vhost -u http://sensores.thl -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt --append-domain -r
De la misma forma que se ha hecho con el dominio, es necesario añadir dicho subdominio junto a la IP correspondiente en el archivo /etc/hosts de la máquina local, ya que parece estar aplicando virtual hosting basado en nombre para servirlo.
sudo mousepad /etc/hosts
10.0.70.6 sensores.thl info.sensores.thl (modificar esta linea y guardar los cambios)sudo mousepad /etc/hosts
10.0.70.6 sensores.thl info.sensores.thl (modificar esta linea y guardar los cambios)Al acceder al subdominio descubierto, resuelve una nueva página web.
URL -> http://info.sensores.thlURL -> http://info.sensores.thl
Esta parece que muestra una página similar pero no igual, ya que esta incluye más contenido.
Al revisar el código fuente, este parece contener un comentario HTML con una pista indicando que la imagen de esta página oculta algo en sus metadatos.
URL -> view-source:http://info.sensores.thl/
...
<!-- Imagen con metadatos ocultos -->URL -> view-source:http://info.sensores.thl/
...
<!-- Imagen con metadatos ocultos -->
Tras descargar la imagen y revisar sus metadatos, se detecta uno denominado "Comment" que contiene un valor codificado en Base64.
wget http://info.sensores.thl/images/sensor_overview.png
file sensor_overview.png
exiftool sensor_overview.pngwget http://info.sensores.thl/images/sensor_overview.png
file sensor_overview.png
exiftool sensor_overview.png
Al descodificarlo, parece contener unas credenciales en texto plano.
echo '<RECORTADO>' | base64 -decho '<RECORTADO>' | base64 -d
Tras probar estas credenciales, resultan ser válidas para el servicio MySQL.
hydra -l acute -p '<RECORTADO>' mysql://10.0.70.6 -I -fhydra -l acute -p '<RECORTADO>' mysql://10.0.70.6 -I -f
Al probarlas, se consigue acceder al SGBD MySQL con estas.
mysql -h 10.0.70.6 --ssl=False -u acute -p
Enter password: <RECORTADO>mysql -h 10.0.70.6 --ssl=False -u acute -p
Enter password: <RECORTADO>
Al revisar la base de datos SensorData, se detecta una tabla "login" que contienen las credenciales del usuario "administrador" donde la contraseña aparece en lo que aparenta ser un hash.
MySQL [(none)]> show databases;
MySQL [(none)]> use SensorData;
MySQL [SensorData]> show tables;
MySQL [SensorData]> select * from login;MySQL [(none)]> show databases;
MySQL [(none)]> use SensorData;
MySQL [SensorData]> show tables;
MySQL [SensorData]> select * from login;
Después de analizarlo y no poder llegar a ninguna conclusión con este hash, se decide continuar enumerando la base de datos utilizando la tabla "information_schema", para así poder entender mejor la estructura de la base de datos, y de esta forma poder detectar alguna posible pista sobre este hash.
Después de enumerar, se detecta un evento registrado para esta base de datos en particular.
Este indica como se define la contraseña para el usuario "administrador" en particular, utilizando en este caso un método para encriptar un contenido generado de una forma aleatoria, utilizando el método AES_ENCRYPT y una clave de cifrado específica.
MySQL> use information_schema;
MySQL [information_schema]> select * from events where EVENT_SCHEMA="SensorData";
...
BEGIN
IF (SELECT COUNT(*) FROM login) = 0 THEN
SET @password_plain = SUBSTRING(MD5(RAND()), 1, 16);
INSERT INTO login (usuario, password)
VALUES ('administrador', HEX(AES_ENCRYPT(@password_plain, '<RECORTADO>')));
END IF;
ENDMySQL> use information_schema;
MySQL [information_schema]> select * from events where EVENT_SCHEMA="SensorData";
...
BEGIN
IF (SELECT COUNT(*) FROM login) = 0 THEN
SET @password_plain = SUBSTRING(MD5(RAND()), 1, 16);
INSERT INTO login (usuario, password)
VALUES ('administrador', HEX(AES_ENCRYPT(@password_plain, '<RECORTADO>')));
END IF;
END
Al conocer la función y los secretos concretos (clave de cifrado y hash resultante), es posible revertir este para obtener la clave utilizada inicialmente.
Por ello, se desarrolla un script escrito en Python para obtener la contraseña en texto plano.
Nota importante: Esto mismo es posible hacerlo directamente desde el SGBD invirtiendo las operaciones. Pero en este caso, se decide hacerse así. Se muestran las referencias utilizadas a continuación para quien tenga interés en hacerlo de la otra forma.
Referencia: https://dev.mysql.com/doc/refman/8.4/en/encryption-functions.html#function_aes-encrypt
Referencia: https://hsmkit.com/guides/aes-encryption-explained/Referencia: https://dev.mysql.com/doc/refman/8.4/en/encryption-functions.html#function_aes-encrypt
Referencia: https://hsmkit.com/guides/aes-encryption-explained/El script resultante es el siguiente:
# decrypt_hash.py
from Crypto.Cipher import AES
import binascii
""" Descifrar la salida de la función AES_ENCRYPT de MySQL"""
""" Esta función usa AES-128-ECB por defecto con padding PKCS#7"""
def decrypt_mysql_aes(encrypted_hex, key):
# Convertir resultado hexadecimal en bytes
encrypted_bytes = binascii.unhexlify(encrypted_hex)
# Codificar en UTF-8 y obtener los primeros 16 bytes de la clave de cifrado (rellenando si es necesario)
key_bytes = key.encode('utf-8').ljust(16, b'\0')[:16]
# Instanciar objeto AES para el descifrado
cipher = AES.new(key_bytes, AES.MODE_ECB)
# Descifrar y almacenar el resultado descifrado
decrypted = cipher.decrypt(encrypted_bytes)
# Obtener la longitud del padding PKCS#7
padding_length = decrypted[-1]
# Devolver el texto plano a su formato original, eliminando el padding añadido
return decrypted[:-padding_length].decode('utf-8')
# Hash de la contraseña a tratar
encrypted_hash = "<TU_HASH_AQUI>"
# Clave de cifrado utilizada para la contraseña
key = "<TU_CLAVE_AQUI>"
try:
# Recuperar contraseña encriptada e imprimirla por pantalla
plain_password = decrypt_mysql_aes(encrypted_hash, key)
print(f"Contraseña recuperada: {plain_password}")
except Exception as e:
print(f"Error: {e}")# decrypt_hash.py
from Crypto.Cipher import AES
import binascii
""" Descifrar la salida de la función AES_ENCRYPT de MySQL"""
""" Esta función usa AES-128-ECB por defecto con padding PKCS#7"""
def decrypt_mysql_aes(encrypted_hex, key):
# Convertir resultado hexadecimal en bytes
encrypted_bytes = binascii.unhexlify(encrypted_hex)
# Codificar en UTF-8 y obtener los primeros 16 bytes de la clave de cifrado (rellenando si es necesario)
key_bytes = key.encode('utf-8').ljust(16, b'\0')[:16]
# Instanciar objeto AES para el descifrado
cipher = AES.new(key_bytes, AES.MODE_ECB)
# Descifrar y almacenar el resultado descifrado
decrypted = cipher.decrypt(encrypted_bytes)
# Obtener la longitud del padding PKCS#7
padding_length = decrypted[-1]
# Devolver el texto plano a su formato original, eliminando el padding añadido
return decrypted[:-padding_length].decode('utf-8')
# Hash de la contraseña a tratar
encrypted_hash = "<TU_HASH_AQUI>"
# Clave de cifrado utilizada para la contraseña
key = "<TU_CLAVE_AQUI>"
try:
# Recuperar contraseña encriptada e imprimirla por pantalla
plain_password = decrypt_mysql_aes(encrypted_hash, key)
print(f"Contraseña recuperada: {plain_password}")
except Exception as e:
print(f"Error: {e}")A continuación, se define un entorno virtual, se instala la dependencia "pycryptodome" necesaria y se ejecuta el script para recuperar la contraseña en texto plano.
virtualenv venv --python=/usr/bin/python3
source venv/bin/activate
pip install pycryptodome
python3 recover_pass.pyvirtualenv venv --python=/usr/bin/python3
source venv/bin/activate
pip install pycryptodome
python3 recover_pass.py
De esta forma, es posible volver al formulario de login e introducir estas credenciales. Esto resulta en superar la primera parte y obtener acceso a un panel de administración que contiene unas credenciales que deben permitir el acceso mediante SSH, ya que es el único servicio que aún no se ha utilizado.
URL: http://sensores.thl/administracion/login.php
Usuario: administrador
Contraseña: <RECORTADO>
URL: http://sensores.thl/administracion/login.php (Autenticado)
...
¡Felicidades, intrépido hacker!
Has superado la primera prueba y has conseguido detener el reloj... por ahora.
El tiempo está a tu favor por un momento. Aprovecha este respiro, analiza tus pasos y prepárate para lo que viene.
La siguiente etapa te espera, y el tiempo volverá a correr en tu contra tan pronto como comiences el próximo reto.
Recuerda: el reloj no perdona, y cada segundo cuenta. ¡Buena suerte!
## Credenciales de Acceso
Usuario: pepito
Contraseña: <RECORTADO>URL: http://sensores.thl/administracion/login.php
Usuario: administrador
Contraseña: <RECORTADO>
URL: http://sensores.thl/administracion/login.php (Autenticado)
...
¡Felicidades, intrépido hacker!
Has superado la primera prueba y has conseguido detener el reloj... por ahora.
El tiempo está a tu favor por un momento. Aprovecha este respiro, analiza tus pasos y prepárate para lo que viene.
La siguiente etapa te espera, y el tiempo volverá a correr en tu contra tan pronto como comiences el próximo reto.
Recuerda: el reloj no perdona, y cada segundo cuenta. ¡Buena suerte!
## Credenciales de Acceso
Usuario: pepito
Contraseña: <RECORTADO>
En este punto, al intentar probar las credenciales SSH este resulta en no ser correctas. Probando otros servicios tampoco parece resultar en credenciales válidas.
hydra -l pepito -p '<RECORTADO>' ssh://10.0.70.6 -I -fhydra -l pepito -p '<RECORTADO>' ssh://10.0.70.6 -I -f
Nota importante: si no se configura una interfaz específica para la máquina, es posible que el acceso SSH no funcione nunca, ni reiniciando.
Por ello, es necesario una nueva red cualquiera configurado con el CIDR 10.0.2.0/24 (recomendable Host-Only) para que las credenciales funcionen. Al volver a iniciar las máquinas se debe comprobar que ambas máquinas se encuentran en este nuevo segmento de red.
nmap -sn 10.0.2.0/24
ip a show eth0nmap -sn 10.0.2.0/24
ip a show eth0
En este punto es necesario volver a adaptar el archivo "/etc/hosts" para volver a acceder utilizando dominios. Esto es necesario ya que al volver a iniciar la máquina, es posible que la contraseña del usuario "pepito" haya cambiado y haya que recuperar esta.
Nota importante: El segmento de red necesario se ha descubierto al revisar los logs de la máquina objetivo en el proceso de arranque, ya que intentaba establecer una IP dentro de un rango de IPs no configurado y se ha llegado a la conclusión que podría ser este el motivo. Otros laboratorios vistos con anterioridad mostraban esta limitación donde se ha visto esta similitud. Además, en el PDF indica una configuración de red, pero no se especifica ningún rango en particular, al no mostrarse en detalle las interfaces de red configuradas. De esta forma es como se ha llegado a la conclusión y confirmado que esta era la razón por la que no funcionaba.
Al volver a probar con el nuevo segmento de red configurado y las credenciales actualizadas del usuario "pepito" volviendo a acceder al panel de administración, en este caso reporta credenciales válidas.
hydra -l pepito -p '<RECORTADO>' ssh://10.0.2.6 -I -fhydra -l pepito -p '<RECORTADO>' ssh://10.0.2.6 -I -f
De esta forma es posible acceder a través de SSH como el usuario "pepito" y obtener así la flag asociada a este.
ssh pepito@10.0.2.6
yes (aceptar conexión sin comprobar autenticidad)
<introducir la contraseña descubierta>
==================================================
Has llegado al umbral de la última prueba... aquí no hay vuelta atrás.
El tiempo se agota y esta vez no habrá segundas oportunidades.
Solo los que realmente comprenden el valor de cada segundo podrán salir victoriosos.
Dispones de 60 minutos para resolver el enigma que se cierne sobre ti.
Cada decisión cuenta, cada error te acerca al abismo.
No recibirás ayuda, ni pistas adicionales... solo el tic-tac implacable del reloj.
Cuando el tiempo termine, este lugar quedará sellado para siempre.
¿Tienes lo que se necesita para superar este reto?
==================================================
...
whoami
id
hostname
ls -al
cat user.txtssh pepito@10.0.2.6
yes (aceptar conexión sin comprobar autenticidad)
<introducir la contraseña descubierta>
==================================================
Has llegado al umbral de la última prueba... aquí no hay vuelta atrás.
El tiempo se agota y esta vez no habrá segundas oportunidades.
Solo los que realmente comprenden el valor de cada segundo podrán salir victoriosos.
Dispones de 60 minutos para resolver el enigma que se cierne sobre ti.
Cada decisión cuenta, cada error te acerca al abismo.
No recibirás ayuda, ni pistas adicionales... solo el tic-tac implacable del reloj.
Cuando el tiempo termine, este lugar quedará sellado para siempre.
¿Tienes lo que se necesita para superar este reto?
==================================================
...
whoami
id
hostname
ls -al
cat user.txt
Además, enumerando desde aquí se detecta dónde intenta realizar esta configuración específica de red que limitaba el acceso por SSH, utilizando para ello Netplan.
En resumen, Netplan es una herramienta de configuración de red en GNU/Linux que permite definir interfaces, direcciones IP, rutas y DNS mediante archivos YAML. Actúa como una capa de abstracción que genera la configuración para backends como systemd-networkd o NetworkManager. Su objetivo es simplificar y unificar la administración de la red en sistemas modernos como Ubuntu.
Referencia: https://netplan.readthedocs.io/en/stable/
cat /etc/netplan/00-installer-config.yamlReferencia: https://netplan.readthedocs.io/en/stable/
cat /etc/netplan/00-installer-config.yaml
Escalada de privilegios (pepito -> root)
Al revisar el historial de comandos ".bash_history" de este usuario, se detectan una serie de comandos utilizados que parecen revisar e interactuar con una librería dinámica denominada "libscaperoom.so".
cat .bash_history
...
readelf -p .rodata /lib/libscaperoom.socat .bash_history
...
readelf -p .rodata /lib/libscaperoom.so
Al utilizar uno de los comandos para revisar su contenido, parece mostrar una serie de cadenas de caracteres que parecen mostrar una contraseña, la utilidad "su" y un mensaje de acceso concedido como el usuario "root".
readelf -p .rodata /lib/libscaperoom.so
...
String dump of section '.rodata':
[ 0] read
[ 5] /proc/%d/comm
[ 13] r
[ 15] su^J
[ 19] <RECORTADO>
[ 2b] [+] Acceso root concedido!
[ 48] [+] Reloj detenido... Buen trabajo!!!
[ 70] /bin/systemctl stop apagar_automatico.service
[ 9e] /bin/bashreadelf -p .rodata /lib/libscaperoom.so
...
String dump of section '.rodata':
[ 0] read
[ 5] /proc/%d/comm
[ 13] r
[ 15] su^J
[ 19] <RECORTADO>
[ 2b] [+] Acceso root concedido!
[ 48] [+] Reloj detenido... Buen trabajo!!!
[ 70] /bin/systemctl stop apagar_automatico.service
[ 9e] /bin/bash
Tras ejecutar la utilidad "su", se consigue acceder como el usuario "root", proporcionando esta cadena de caracteres como su contraseña. Esto permite además obtener la flag asociada a este usuario.
su - root
Password: <RECORTADO>
whoami
id
hostname
cd /root
ls -al
cat root.txt
...
¡ENHORABUENA, INTRÉPIDO HACKER!
Has logrado superar todos los desafíos y escapar de esta sala virtual. El tiempo no fue tu enemigo,
sino tu aliado, y cada decisión te ha llevado hasta este momento.
La clave para tu victoria es:
<RECORTADO>
Esta flag es el símbolo de tu éxito y la prueba de que has alcanzado el nivel más alto de este reto.
Guarda este logro con orgullo, pues no todos pueden llegar tan lejos.
Recuerda:
- Cada pista que descifraste fue una lección valiosa.
- Cada error que cometiste, una oportunidad de crecer.
- Cada éxito, un paso más hacia el dominio.
Esto no es el final, sino el comienzo de nuevos desafíos. ¿Estás preparado para lo que viene?
¡Nos vemos en el próximo reto, donde tu ingenio será puesto a prueba una vez más!
==================================================su - root
Password: <RECORTADO>
whoami
id
hostname
cd /root
ls -al
cat root.txt
...
¡ENHORABUENA, INTRÉPIDO HACKER!
Has logrado superar todos los desafíos y escapar de esta sala virtual. El tiempo no fue tu enemigo,
sino tu aliado, y cada decisión te ha llevado hasta este momento.
La clave para tu victoria es:
<RECORTADO>
Esta flag es el símbolo de tu éxito y la prueba de que has alcanzado el nivel más alto de este reto.
Guarda este logro con orgullo, pues no todos pueden llegar tan lejos.
Recuerda:
- Cada pista que descifraste fue una lección valiosa.
- Cada error que cometiste, una oportunidad de crecer.
- Cada éxito, un paso más hacia el dominio.
Esto no es el final, sino el comienzo de nuevos desafíos. ¿Estás preparado para lo que viene?
¡Nos vemos en el próximo reto, donde tu ingenio será puesto a prueba una vez más!
==================================================
En este punto, al haber obtenido acceso a la cuenta "root", se ha conseguido obtener los máximos privilegios posibles sobre el sistema objetivo (este laboratorio).
BONUS 1: Descifrando archivo GPG encontrado
Al revisar el directorio principal del usuario "pepito", se detecta un archivo GPG.
En resumen, un archivo GPG es un archivo protegido mediante cifrado o firmado digitalmente usando GNU Privacy Guard** (GPG)**. Sirve para mantener la información confidencial, asegurando que solo el destinatario autorizado pueda leerla, o para verificar la autenticidad e integridad de un archivo o mensaje mediante una firma digital.
ls -al
file leeme.txt.gpgls -al
file leeme.txt.gpg
En este punto se descarga a la máquina de trabajo para analizarse más detenidamente.
scp pepito@10.0.2.6:/home/pepito/leeme.txt.gpg ./leeme.txt.gpg
(introducir la contraseña de "pepito")
file leeme.txt.gpgscp pepito@10.0.2.6:/home/pepito/leeme.txt.gpg ./leeme.txt.gpg
(introducir la contraseña de "pepito")
file leeme.txt.gpg
A continuación se extrae el hash asociado a este archivo y se intenta romper. No tarda mucho hasta que encuentra la contraseña asociada.
gpg2john leeme.txt.gpg > leeme.hash
john --wordlist=/usr/share/wordlists/rockyou.txt leeme.hashgpg2john leeme.txt.gpg > leeme.hash
john --wordlist=/usr/share/wordlists/rockyou.txt leeme.hash
Conociendo la contraseña, es posible extraer el contenido que protege. En este caso, consiste en un archivo de texto plano que contiene una pista que apunta a la escalada de privilegios realizada previamente.
gpg --output leeme.txt --decrypt leeme.txt.gpg
(introducir la contraseña descubierta)
file leeme.txt
cat leeme.txt
...
No todas las funciones tienen el control que parecen tener. Algunas veces, quien controla lo que se **carga primero** tiene la ventaja. Recuerda: la pre-carga puede ser tu mejor aliada... o tu perdición.gpg --output leeme.txt --decrypt leeme.txt.gpg
(introducir la contraseña descubierta)
file leeme.txt
cat leeme.txt
...
No todas las funciones tienen el control que parecen tener. Algunas veces, quien controla lo que se **carga primero** tiene la ventaja. Recuerda: la pre-carga puede ser tu mejor aliada... o tu perdición.
Revisando los elementos detectados en la escalada, se puede comprobar que la utilidad "su" depende de la librería dinámica denominada "libscaperoom.so", donde previamente se detectaron las credenciales del usuario "root".
which su
file /usr/bin/su
ldd /usr/bin/su
ls -al /lib/libscaperoom.sowhich su
file /usr/bin/su
ldd /usr/bin/su
ls -al /lib/libscaperoom.so
Además, buscando por parte del nombre se termina detectando el código fuente de esta librería. Se puede comprobar cómo utiliza la clave secreta encontrada previamente para validar el acceso a un intérprete de comandos en el contexto de "root".
find / -name *scaperoom* 2>/dev/null
cat /usr/lib/libscaperoom.cfind / -name *scaperoom* 2>/dev/null
cat /usr/lib/libscaperoom.c
Por último, se detecta esta librería dinámica definida dentro del archivo "/etc/ld.so.preload", el cual indica al cargador dinámico de Linux que cargue esta librería antes que cualquier otra, afectando a todos los procesos que utilizan librerías dinámicas.
ls -al /etc/ld.so.preload
cat /etc/ld.so.preloadls -al /etc/ld.so.preload
cat /etc/ld.so.preload
BONUS 2: Obteniendo la contraseña real de "root"
Desde el contexto de "root", se obtiene su hash accediendo al archivo "/etc/shadow".
cat /etc/shadowcat /etc/shadow
Una vez obtenido el hash asociado al usuario "root", se intenta romper. No tarda mucho hasta que detecta la contraseña, la cual es distinta a la cadena de caracteres encontrada previamente.
mousepad root.hash -> (pegar y guardar el hash)
john --wordlist=/usr/share/wordlists/rockyou.txt root.hashmousepad root.hash -> (pegar y guardar el hash)
john --wordlist=/usr/share/wordlists/rockyou.txt root.hash
Con esta contraseña es posible acceder a la cuenta del usuario "root" mediante la utilidad "su". Esto se debe a que la librería intercepta el proceso de autenticación y concede el acceso cuando se introduce una cadena de caracteres específica. Si dicha cadena no coincide, la utilidad "su" continúa con su funcionamiento habitual y realiza las comprobaciones de autenticación normales.
su - root
(introducir la contraseña real de "root" detectada)
whoami
id
hostname
ls -al
cat root.txt
...
==================================================
¡ENHORABUENA, INTRÉPIDO HACKER!
Has logrado superar todos los desafíos y escapar de esta sala virtual. El tiempo no fue tu enemigo,
sino tu aliado, y cada decisión te ha llevado hasta este momento.
La clave para tu victoria es:
<RECORTADO>
Esta flag es el símbolo de tu éxito y la prueba de que has alcanzado el nivel más alto de este reto.
Guarda este logro con orgullo, pues no todos pueden llegar tan lejos.
Recuerda:
- Cada pista que descifraste fue una lección valiosa.
- Cada error que cometiste, una oportunidad de crecer.
- Cada éxito, un paso más hacia el dominio.
Esto no es el final, sino el comienzo de nuevos desafíos. ¿Estás preparado para lo que viene?
¡Nos vemos en el próximo reto, donde tu ingenio será puesto a prueba una vez más!
==================================================su - root
(introducir la contraseña real de "root" detectada)
whoami
id
hostname
ls -al
cat root.txt
...
==================================================
¡ENHORABUENA, INTRÉPIDO HACKER!
Has logrado superar todos los desafíos y escapar de esta sala virtual. El tiempo no fue tu enemigo,
sino tu aliado, y cada decisión te ha llevado hasta este momento.
La clave para tu victoria es:
<RECORTADO>
Esta flag es el símbolo de tu éxito y la prueba de que has alcanzado el nivel más alto de este reto.
Guarda este logro con orgullo, pues no todos pueden llegar tan lejos.
Recuerda:
- Cada pista que descifraste fue una lección valiosa.
- Cada error que cometiste, una oportunidad de crecer.
- Cada éxito, un paso más hacia el dominio.
Esto no es el final, sino el comienzo de nuevos desafíos. ¿Estás preparado para lo que viene?
¡Nos vemos en el próximo reto, donde tu ingenio será puesto a prueba una vez más!
==================================================
BONUS 3: Inspección del servicio de apagado
Tras inspeccionar el servicio detectado al utilizar la cadena de caracteres para acceder por primera vez como "root", resulta ser el encargado delimitar el tiempo para resolver el reto. Al pasar 60 minutos si no se ha completado, este se encarga de apagar la máquina objetivo automáticamente.
systemctl cat apagar_automatico.service
ls -al /usr/local/bin/scr1.sh
cat /usr/local/bin/scr1.sh
ls -al /etc/systemd/system/apagar_automatico.servicesystemctl cat apagar_automatico.service
ls -al /usr/local/bin/scr1.sh
cat /usr/local/bin/scr1.sh
ls -al /etc/systemd/system/apagar_automatico.service
Mitigaciones a aplicar
- Almacenar o compartir la información sensible como contraseñas, hashes, notas, nombres de usuario o secretos similares de una forma segura (por ejemplo, usando gestores de contraseñas).
- Evitar aplicar prácticas del tipo "seguridad por oscuridad", aplicando mecanismos de seguridad robustos y auditables con el fin de asegurar funcionalidades críticas o proteger secretos.
- Evitar que los usuarios del sistema u otros servicios críticos tengan como contraseña una que se pueda encontrar en listas públicas o conocidas como rockyou. Recomendación: crear una política de contraseñas robusta para evitar que esto ocurra.
- Ajustarse al principio de privilegio mínimo y conceder a los usuarios del sistema única y exclusivamente los privilegios que vayan a necesitar. Aplica de la misma forma para recursos del sistema y sus permisos. Recomendación: existen guías de hardening como "CIS Benchmarks" para aplicar buenas prácticas y asegurar entre otras cosas, los permisos para distintos tipos de software y sistemas expuestos en Internet.
¿Te gustó esta publicación? Sígueme y descubre más en mi blog principal: https://pyth0nk1d.medium.com