Nibbles
Un blog Nibbleblog 4.0.3 escondido en un directorio oculto cae por un file upload autenticado tras saltarse su protección anti-fuerza-bruta con la cabecera X-Forwarded-For, y un monitor.sh world-writable ejecutable con sudo abre la puerta a root.
Nibbles
| Máquina | SO | Dificultad | IP |
|---|---|---|---|
| Nibbles | Linux | Easy | 10.129.96.84 |
A tener en cuenta...
Resumen
Nibbles es un Linux de dificultad fácil, pero de los que enseñan más que muchos de dificultad media: casi todo el trabajo está en la enumeración. El puerto web no muestra nada — un simple Hello world! — y el camino real sólo aparece si te molestas en leer el código fuente de la página.
Ahí dentro hay un Nibbleblog, un gestor de blogs en PHP, en una versión con un fallo conocido. El problema es que explotarlo requiere estar autenticado, y el panel bloquea tu IP si fallas demasiadas veces al intentar adivinar la contraseña. La gracia de la máquina está en saltarse ese bloqueo falsificando la IP de origen con una cabecera HTTP.
Una vez dentro, un file upload da ejecución de código, y la escalada es un clásico de libro: un script que podemos ejecutar como root con sudo… y sobre el que además tenemos permiso de escritura.
Vulnerabilidad
Tres piezas encadenadas: una para descubrir el objetivo, otra para entrar y otra para quedarse con la máquina.
01 · Credenciales débiles y bypass del bloqueo por IP
El panel de administración de Nibbleblog protege el login metiendo en una blacklist temporal la IP que falla varias veces seguidas. Pero para decidir qué IP bloquear se fía de cabeceras como X-Forwarded-For, que el cliente controla. Rotando el valor de esa cabecera en cada petición, cada intento parece venir de una IP distinta y el bloqueo nunca llega a saltar — lo que deja vía libre a un ataque de fuerza bruta contra una contraseña, además, débil.
02 · Arbitrary File Upload en Nibbleblog 4.0.3 (autenticado)
El plugin My image de Nibbleblog 4.0.3 «Coffee» no valida la extensión ni el tipo del fichero que se sube. Un administrador autenticado puede subir un .php en lugar de una imagen y acceder a él en /content/private/plugins/my_image/, consiguiendo ejecución remota de código. Está automatizado en el módulo de Metasploit nibbleblog_file_upload.
03 · Escalada por sudo sobre un script modificable
El usuario nibbler puede ejecutar como root y sin contraseña el script monitor.sh. El fallo es doble: no sólo está en la lista de sudo, sino que sus permisos son -rwxrwxrwx, así que cualquiera puede reescribir su contenido. Metemos dentro una shell y la ejecutamos con sudo: se lanza como root.
Reconocimiento
Caja negra: lo primero es ver qué hay escuchando. Barrido completo de puertos contra la víctima, pidiendo de paso que adivine el sistema operativo
| Puerto | Servicio |
| 22 | ssh |
| 80 | http |
Sólo dos puertos: 22 (SSH) y 80 (HTTP), y un sistema que nmap sitúa en un Linux 3.X|4.X. Sin credenciales, SSH no da juego de momento, así que todo el peso recae en el servidor web.

Enumeración
Afino versión sobre los dos puertos abiertos

Un Apache 2.4.18 sobre Ubuntu Xenial y un OpenSSH acorde. Confirmo el servidor con whatweb, que no añade gran cosa

Un fuzzing de rutas sobre la raíz tampoco revela nada interesante: apenas el index.html y un /server-status protegido

Y la web, en efecto, no tiene nada: un escueto Hello world! y punto

Aquí es donde la máquina premia la curiosidad. Antes de rendirme, miro el código fuente de esa página tan vacía, y entre las líneas hay un comentario que lo cambia todo

Ese «nada interesante por aquí» es, por supuesto, justo lo contrario. En /nibbleblog/ aparece un blog de verdad: Nibbles — Yum yum, montado sobre Nibbleblog

Con un objetivo real delante, vuelvo a enumerar, ahora sobre el blog. Wappalyzer sólo delata RSS y jQuery

y whatweb confirma el gestor: Nibbleblog, con cookie PHPSESSID y el título Nibbles - Yum yum

Fuzzeo también el directorio del blog, y aquí sí hay carne: un panel admin.php, un install.php, un update.php, el README y, sobre todo, un /content/ con directory indexing activado

Con el directory listing abierto, toca navegar a mano. El /content/ cuelga tres carpetas: private, public y tmp

En /content/public/upload/ ya se intuye por dónde vendrá el ataque — es donde Nibbleblog guarda lo que se sube

pero lo jugoso está en /content/private/: ficheros de configuración en XML sin ninguna protección

Entre ellos, el update.php y el config.xml confirman la versión exacta — Nibbleblog 4.0.3 «Coffee» — y filtran el correo del administrador, admin@nibbles.com


El README remacha el dato de la versión

Y un nikto de paso sobre el blog destaca justo lo que ya sospechábamos: directory indexing, el panel admin.php y acceso a la configuración

El fichero que más me interesa es el users.xml: ahí enumero los usuarios del panel. Sólo hay uno — admin — y de paso veo la blacklist de IPs bloqueadas por intentos fallidos

Tengo usuario pero no contraseña. La opción obvia es la fuerza bruta contra admin.php, pero aquí está el truco de la máquina: en un intento anterior comprobé que tras unas pocas peticiones fallidas el panel mete tu IP en esa blacklist y te corta. Así que monto el ataque con Burp Suite — un login normal con admin:password devuelve el típico «Incorrect username or password»

La idea para esquivar el bloqueo es falsificar la IP de origen con la cabecera X-Forwarded-For. Primero verifico que el servidor la acepta


y que admite el fuzz: cambiando su valor en cada petición, cada intento llega como si viniera de una IP nueva, así que el bloqueo por IP nunca se dispara y la fuerza bruta puede correr sin frenos

Con el bloqueo fuera de juego, la fuerza bruta sobre la contraseña de admin termina devolviendo una credencial tan pobre como el nombre de la propia máquina: admin:nibbles.
Explotación
Ya autenticado y con la versión fijada, busco qué arrastra ese Nibbleblog 4.0.3

El que encaja es el Arbitrary File Upload, pero sólo viene como módulo .rb de Metasploit, así que me obliga a tirar de la consola. Cargo el módulo, le paso las credenciales y la ruta del blog, y lo lanzo
El módulo sube un image.php malicioso a través del plugin My image, lo invoca para disparar la shell y lo borra para no dejar rastro. Al otro lado tengo ejecución de comandos como nibbler

Esa sesión es una shell básica php/php, incómoda para moverse. La promociono a una meterpreter con el módulo shell_to_meterpreter, que además me da una shell mucho más estable

Desde la meterpreter abro una shell interactiva, me paso por el /bin/bash -i y salto al home de nibbler, donde ya me espera la primera bandera

Escalada de privilegios
Lo primero al aterrizar como nibbler es comprobar qué puedo ejecutar con privilegios

Puedo lanzar monitor.sh como root y sin contraseña. El detalle es que, junto a user.txt, en el home hay un personal.zip, y ese script vive dentro. Lo descomprimo para tenerlo en disco

Y aquí está el regalo: el monitor.sh tiene permisos -rwxrwxrwx, es decir, es escribible por cualquiera. Como además lo puedo ejecutar como root, basta con cambiar su contenido por una shell

Intento editarlo con nano, pero la shell no es un terminal de verdad y me lo rechaza con un «Error opening terminal: unknown»

No hace falta un editor para esto. Reescribo el script entero de un plumazo con echo y una redirección, dejándolo con una única línea que lanza una shell

Ahora sólo queda ejecutarlo con sudo: el script corre como root y, al ser nuestra shell, nos deja una consola con el máximo privilegio. Desde ahí leo la última bandera

Flags
La de usuario, en el home de nibbler
Y la de root, tras la escalada
Cómo se arregla
La máquina acumula varios fallos pequeños que, juntos, dan root. Por capas:
- Actualizar Nibbleblog: la versión 4.0.3 arrastra el file upload del plugin My image. Migrar a una versión soportada — o abandonar un gestor sin mantenimiento activo — cierra el vector de entrada.
- No fiarse de X-Forwarded-For: la protección anti-fuerza-bruta debe basarse en la IP real de la conexión, no en una cabecera que el cliente puede falsificar. Mejor aún, combinarla con rate-limiting, bloqueo por cuenta y un segundo factor.
- Contraseñas fuertes: nibbles como contraseña de admin se cae con cualquier diccionario. Credenciales largas y únicas convierten la fuerza bruta en inviable aunque el bypass del bloqueo funcione.
- Desactivar el directory indexing: el listing de /content/ expone configuración, usuarios y la versión exacta. Apagarlo en Apache y proteger /content/private/ corta media enumeración.
- Revisar los permisos de sudo: un script ejecutable como root nunca debe ser escribible por el usuario que lo lanza. Quitar los permisos -rwxrwxrwx de monitor.sh (o sacarlo de la lista de sudo) elimina la escalada.
Conclusiones
Buena máquina, de nivel sencillo, recomendable