// 01
Reconocimiento
// NOTA
El ttl=63 es la huella de un sistema Linux (que parte de 64) con un salto de red menos: lo normal es que la respuesta atraviese un router (en este caso, seguramente la VPN de HackTheBox). Confirmada la conectividad, toca enumerar puertos.
// NOTA
El puerto 80 es la pieza que importa: nginx sirve una instancia de GitLab (el título de la página y las rutas de robots.txt lo delatan). El 22 es SSH, pero sin credenciales no sirve de entrada. El 8060 solo devuelve un 404 y el 9094 no se identifica, así que los dejamos para más adelante.
// NOTA
Es opcional, pero convierte el XML en un informe HTML cómodo de leer en el navegador, con los puertos y los scripts ordenados por servicio.
// 02
Enumeración web y CVE
En http://10.129.229.69/ aparece el inicio de sesión de
GitLab Community Edition. Lo importante no es el login, sino el
enlace «Don't have an account yet? Register now»: la instancia permite
registrarse sin invitación, y esa es la condición que necesita el exploit.
Nos registramos con un nombre cualquiera, el usuario prueba (disponible) y la contraseña
password.123, que es la que usa el PoC más adelante. El correo puede ser cualquiera.
// NOTA
Es una cuenta desechable de laboratorio. El PoC la necesita para crear grupos, proyectos y adjuntos, así que no hace falta ningún privilegio extra.
La página de ayuda de GitLab (ruta /help) muestra su versión exacta:
// VERSIÓN AFECTADA
GitLab CE 16.0.0 es la versión que el PoC del CVE-2023-2825 declara como vulnerable. La versión exacta es el dato clave: con ella, el CVE y su PoC encajan sin más pruebas.
// 03
Preparación del PoC
Usamos el repositorio CVE-2023-2825-PoC. Según su descripción, el script inicia sesión con una cuenta válida, crea la estructura de grupos públicos anidados, crea un proyecto público, sube un adjunto y aprovecha la ruta de subida vulnerable para leer un archivo del servidor. También admite reutilizar una ruta de subida ya existente.
Si intentamos pip install directamente, Kali rechaza la instalación con
externally-managed-environment (PEP 668). En lugar de forzarla con
--break-system-packages, creamos un entorno virtual: es la opción limpia.
// NOTA
El prompt (venv) confirma que pip instala dentro del entorno y no toca el Python del sistema. Hay que activar el venv en cada terminal nueva antes de lanzar el script.
// 04
Explotación
La primera ejecución hace todo el trabajo: crea los grupos, el proyecto y el adjunto, y después lee el archivo que pedimos.
Probamos con /etc/hosts porque es pequeño y confirma que la lectura funciona:
// RUTA REUTILIZABLE
La línea Reusable upload path es la clave del PoC: guarda la ruta del adjunto que acabamos de subir. Las rutas
(O1K-…, poc-… y el hash) son las de mi ejecución; en cada máquina cambian, así que hay que copiar
la que imprima la tuya. Además, /etc/hosts ya revela el nombre getlab.htb.
Con --reuse-path el script se salta la creación de grupos, proyecto y adjunto, y lee directamente desde la ruta guardada.
Es mucho más rápido para leer varios archivos seguidos:
Con la ruta reutilizable ya comprobada, pedimos /etc/passwd: la lista de usuarios del sistema con su shell de inicio.
// LECTURA ARBITRARIA DE ARCHIVOS
Dónde: la ruta de subida de adjuntos de GitLab, que el PoC hace atravesar hasta la raíz del sistema (path traversal).
Qué permite: leer cualquier archivo al que tenga acceso el usuario que ejecuta GitLab, con cualquier cuenta registrada y sin privilegios de administrador.
Resultado: /etc/passwd confirma los usuarios reales de la máquina, entre ellos root y sam (uid 1000, con shell /bin/bash).
Con esto queda demostrada la vulnerabilidad: el servidor entrega archivos del sistema a cualquier cuenta registrada.
// ALCANCE DEL WRITEUP
Este writeup documenta el reconocimiento, la identificación de GitLab 16.0.0 y la demostración del CVE-2023-2825: la lectura de archivos del servidor con el PoC, hasta /etc/passwd. El resto de la máquina no forma parte de esta publicación.
// NOTA
El PoC crea 11 grupos anidados antes del proyecto. Según su diseño, esa profundidad de ruta es lo que le permite
recorrer directorios hacia arriba hasta la raíz del servidor: sin ella, la lectura no llega a /etc/passwd.
// 05
Referencia Comandos
- -c 3 → envía 3 paquetes ICMP y termina.
- -p- → Escanea los 65535 puertos TCP.
- -sS → Escaneo SYN ("half-open"), rápido y discreto.
- -sC → Lanza los scripts por defecto de nmap (NSE).
- -sV → Detecta la versión exacta de cada servicio.
- -n → No resuelve DNS.
- -Pn → Trata el host como activo, sin ping previo.
- --min-rate=5000 → Envía al menos 5000 paquetes por segundo.
- --open → Muestra solo los puertos abiertos.
- -oX → Guarda el resultado en XML.
- nmap.xsl → Hoja de estilo oficial que da formato al informe.
--break-system-packages.- -m venv → Ejecuta el módulo que crea el entorno.
- source venv/bin/activate → Activa el entorno en la terminal actual.
- pip install -r requirements.txt → Instala las dependencias del PoC dentro del entorno.
- --url → Dirección de la instancia de GitLab.
- --username / --password → Cuenta registrada en la instancia.
- --file → Archivo del servidor que queremos leer.
- --reuse-path → Ruta de subida ya creada, para no repetir el proceso.
// 06
Glosario
../ para salir del directorio previsto y acceder a rutas arbitrarias del sistema de ficheros.
Es una de las vulnerabilidades más comunes en aplicaciones web con subida o lectura de archivos.
pip instalar paquetes en el Python gestionado por el sistema operativo. Kali lo aplica, por eso el error aparece al instalar sin entorno virtual.