Imagery
Executive summary — Imagery is a Flask image-gallery app with a five-step chain, each step a different class of vulnerability. A stored XSS in the bug-report system steals an admin bot's cookie; with that cookie, a local file inclusion (LFI) in the admin panel leaks source code and a hash database; an image-editing feature flagged "in development" turns out to carry a real command injection; an pyAesCrypt-encrypted backup is dictionary-brute-forced; and the final escalation abuses a homegrown backup tool (
charcol) that lets you both reset its own protection and create an arbitrary cron job running as root.
| Platform | Hack The Box |
| Operating system | Linux |
| Difficulty | Medium |
| Status | Retired |
| Target IP | 10.129.242.164 |
Attack map
[8000] "Image Gallery" (Flask) — report_bug renders report.details unsanitized
│ Stored XSS → steals the admin bot's cookie (reviews reports)
▼
[LFI] /admin/get_system_log?log_identifier=../db.json (with the admin cookie)
│ db.json + source code → testuser's MD5 hash → iambatman
▼
[RCE] Command injection in apply_visual_transform (crop, shell=True) → 'web'
│ backup /var/backup/*.zip.aes (pyAesCrypt) → brute-forced → bestfriends
│ old backup db.json: mark's MD5 hash → supersmash
▼
[SU] mark (user.txt)
│ sudo NOPASSWD /usr/local/bin/charcol
│ -R resets the master passphrase to "no password" + auto add = cron as root
▼
[ROOT] cron injection via charcol → root.txt
1. Reconnaissance
nmap -sT -p- --min-rate 3000 -T4 -Pn -oN m6_allports.txt 10.129.242.164
nmap -sT -sCV -p22,8000 -Pn -oN m6_services.txt 10.129.242.164
22/tcp open ssh OpenSSH 9.7p1 Ubuntu 7ubuntu4.3
8000/tcp open http Werkzeug httpd 3.1.3 (Python 3.12.7) [Image Gallery]
An SPA-style Flask "Image Gallery" app, with registration/login over JSON:
B=http://10.129.242.164:8000
curl -s -c cj.txt -X POST $B/register -H "Content-Type: application/json" -d '{"username":"pwn","password":"Passw0rd123!"}'
curl -s -c cj.txt -b cj.txt -X POST $B/login -H "Content-Type: application/json" -d '{"username":"pwn","password":"Passw0rd123!"}'
The real endpoints are pulled straight from the SPA's own JavaScript: /upload_image, /images, /report_bug, /convert_image, /apply_visual_transform, /edit_image_details, /delete_image_metadata, and a whole family of /admin/{users,bug_reports,get_system_log,delete_user,delete_bug_report} plus /auth_status.
Two distinct roles in the app:
isAdminandisTestuser. Several features respond with the literal message "Feature is still in development" — a hint that there are half-protected, role-gated features worth examining closely later on.
Resumen ejecutivo — Imagery es una aplicación Flask de galería de imágenes con una cadena de cinco pasos, cada uno de un tipo de vulnerabilidad distinto. Un XSS almacenado en el sistema de reportes de bugs roba la cookie de un bot administrador; con esa cookie, una lectura de fichero local (LFI) en el panel de admin filtra el código fuente y una base de datos con hashes; una función de edición de imágenes marcada «en desarrollo» resulta tener una inyección de comandos real; un backup cifrado con pyAesCrypt se fuerza por diccionario; y la escalada final abusa de una herramienta de backups propia (
charcol) que permite tanto resetear su propia protección como crear un cron job arbitrario ejecutado como root.
| Plataforma | Hack The Box |
| Sistema operativo | Linux |
| Dificultad | Medium |
| Estado | Retired |
| IP objetivo | 10.129.242.164 |
Mapa del ataque
[8000] "Image Gallery" (Flask) — report_bug renderiza report.details sin sanear
│ Stored XSS → roba la cookie del bot admin (revisa reportes)
▼
[LFI] /admin/get_system_log?log_identifier=../db.json (con cookie de admin)
│ db.json + código fuente → hash MD5 de testuser → iambatman
▼
[RCE] Command Injection en apply_visual_transform (crop, shell=True) → 'web'
│ backup /var/backup/*.zip.aes (pyAesCrypt) → fuerza bruta → bestfriends
│ db.json antiguo del backup: hash MD5 de mark → supersmash
▼
[SU] mark (user.txt)
│ sudo NOPASSWD /usr/local/bin/charcol
│ -R resetea la passphrase maestra a "sin contraseña" + auto add = cron como root
▼
[ROOT] cron injection vía charcol → root.txt
1. Reconocimiento
nmap -sT -p- --min-rate 3000 -T4 -Pn -oN m6_allports.txt 10.129.242.164
nmap -sT -sCV -p22,8000 -Pn -oN m6_services.txt 10.129.242.164
22/tcp open ssh OpenSSH 9.7p1 Ubuntu 7ubuntu4.3
8000/tcp open http Werkzeug httpd 3.1.3 (Python 3.12.7) [Image Gallery]
Una app Flask «Image Gallery» tipo SPA, con registro/login vía JSON:
B=http://10.129.242.164:8000
curl -s -c cj.txt -X POST $B/register -H "Content-Type: application/json" -d '{"username":"pwn","password":"Passw0rd123!"}'
curl -s -c cj.txt -b cj.txt -X POST $B/login -H "Content-Type: application/json" -d '{"username":"pwn","password":"Passw0rd123!"}'
Los endpoints reales se extraen del propio JavaScript de la SPA: /upload_image, /images, /report_bug, /convert_image, /apply_visual_transform, /edit_image_details, /delete_image_metadata, y toda una familia /admin/{users,bug_reports,get_system_log,delete_user,delete_bug_report} más /auth_status.
Dos roles distintos en la app:
isAdmineisTestuser. Varias funciones responden literalmente «Feature is still in development» — una pista de que hay features a medio proteger, gateadas por rol, que merece la pena revisar con detalle más adelante.
This content is Root Access only. Everything else on the site — the free tier, the whole public library — stays open.
See Root Access plansNo account? Create one free then upgrade from your console.
Este contenido es solo para Root Access. Todo lo demás del sitio — el nivel gratuito, toda la biblioteca pública — sigue abierto.
Ver planes de Root Access¿Sin cuenta? Crea una gratis y luego mejora desde tu consola.