Ir al contenido

Writeup de la Máquina "Support" en Hack The Box: Guía Detallada

3 de mayo de 2026 por
Writeup de la Máquina "Support" en Hack The Box: Guía Detallada
Gerardo

Máquina: Support | OS: Windows Server 2022 | Dificultad: Easy | Dominio: support.htb | Categoría: Active Directory | Vector principal: RBCD Attack




Este writeup documenta la resolución completa de la máquina Support de HackTheBox. El camino de ataque inicia con una enumeración SMB sin credenciales, pasa por el análisis estático de un binario .NET para extraer credenciales LDAP, continúa con la enumeración del directorio activo para obtener acceso inicial via WinRM y finaliza con una escalada de privilegios mediante un ataque de Resource-Based Constrained Delegation (RBCD) que otorga acceso SYSTEM al Domain Controller.


Cadena de ataque

Antes de entrar en detalle, es útil tener el mapa completo del ataque para  entender hacia dónde apunta cada decisión:


  1. Reconocimiento (Nmap): Identificamos un Domain Controller con SMB, LDAP, Kerberos y WinRM expuestos.

  2. Enumeración SMB sin credenciales: Un share llamado support-tools es accesible sin autenticación y contiene un binario custom.

  3. Análisis estático del binario .NET: El binario contiene credenciales LDAP hardcodeadas que extraemos por reversing.

  4. Enumeración LDAP autenticada: Con las credenciales LDAP volcamos todos los usuarios del dominio y encontramos que el usuario support tiene su contraseña guardada en un campo de descripción del AD.

  5. Acceso inicial via WinRM: La cuenta support pertenece al grupo Remote Management Users, lo que permite obtener una shell.

  6. Enumeración de ACLs con BloodHound: Descubrimos que support es miembro de Shared Support Accounts, grupo con GenericAll sobre el objeto DC$ en el AD.

  7. Escalada RBCD: Aprovechamos ese permiso para configurar delega

Reconocimiento con Nmap

El primer paso en cualquier prueba de penetración es identificar los servicios expuestos en el objetivo. Ejecutamos un escaneo con detección de versiones (-sV) y scripts NSE por defecto (-sC). La flag -Pn desactiva el ping previo, útil cuando el host no responde ICMP pero sí tiene puertos abiertos.

Terminal

nmap -sV -sC -Pn 10.129.47.81
        


El output del escaneo revela inmediatamente el perfil de un Domain Controller de Windows. Los puertos clave son: 53 (DNS), 88 (Kerberos), 389 y 3268 (LDAP y  Global Catalog), 445 (SMB) y 5985 (WinRM). El script smb2-security-mode informa que el firmado de mensajes está habilitado y requerido, lo que descarta ataques de relay NTLM. El dominio se llama support.htb y el hostname del DC es simplemente DC. El puerto 5985 (WinRM) abierto es especialmente valioso: si en algún momento obtenemos credenciales de un usuario con permisos de acceso remoto, podremos obtener una shell sin necesidad de explotar ninguna vulnerabilidad adicional.


Enumeración SMB Null Session

Con SMB disponible, el siguiente paso natural es verificar si el servidor permite null sessions, es decir, conexiones sin proporcionar credenciales. Esto es una configuración errónea relativamente común, especialmente en entornos legacy o mal configurados. Usamos netexec (nxc) que simplifica esta verificación:

Terminal

nxc smb 10.129.47.81 -u guest -p "" --shares
        


El resultado muestra que el share support-tools es accesible con permisos de lectura sin necesidad de autenticación. El resto de shares (ADMIN$, C$, NETLOGON, SYSVOL) están restringidos, lo cual es lo esperado en un DC. El share anómalo es support-tools: su nombre sugiere que contiene herramientas internas del equipo de soporte, lo que lo convierte en el objetivo inmediato.


Conectamos al share para listar su contenido:

Terminal

smbclient -N //10.129.47.81/support-tools -c 'ls'
        


Encontramos varias herramientas conocidas (7-Zip, Notepad++, PuTTY, Sysinternals, Wireshark) que no presentan mayor interés. El archivo que destaca es  UserInfo.exe.zip: un binario que no corresponde a ningún software comercial conocido, lo que indica que fue desarrollado internamente. Las herramientas internas suelen ser candidatas ideales para contener credenciales hardcodeadas, ya que rara vez pasan por revisiones de seguridad formales. Lo descargamos:

Terminal

smbclient -N //10.129.47.81/support-tools -c 'get UserInfo.exe.zip'
        


Terminal

unzip UserInfo.exe.zip
        

Análisis Estático del BinarioReverse Engineering .NET


Al descomprimir el archivo, obtenemos UserInfo.exe acompañado de múltiples DLLs del runtime de .NET (System.Buffers.dll, System.Memory.dll, etc.) y un archivo UserInfo.exe.config. Este conjunto de archivos confirma que se trata de un binario

.NET, lo cual es excelente para nuestros propósitos: a diferencia del código nativo compilado en C o C++, el IL (Intermediate Language) de .NET conserva nombres de métodos, clases y variables, haciendo el análisis estático mucho más directo. Comenzamos con una búsqueda rápida de strings relacionadas con contraseñas para tener una primera orientación antes de profundizar en el IL:

Terminal

strings UserInfo.exe | grep -i "pass"
        


El output muestra dos strings relevantes: getPassword (nombre de un método) y enc_password (nombre de un campo, probablemente una contraseña encodeada). Esto confirma que el binario maneja credenciales internamente. El siguiente paso es ver exactamente cómo funciona ese método, para lo cual usamos monodis, el desensamblador incluido en el runtime de Mono para .NET:

Terminal

monodis UserInfo.exe | grep -A 20 "getPassword"
        


El IL descompilado revela la lógica del método con claridad. Las instrucciones más importantes son: ldsfld que carga el campo estático enc_password (la contraseña encodeada almacenada en la clase Protected) y la llamada a System.Convert::FromBase64String que la decodifica de Base64. El resto del método implementa un loop XOR con una clave hardcodeada, que es el mecanismo de "cifrado" empleado.


Para entender cómo se usan esas credenciales, analizamos el constructor estático (.cctor) de la clase, que es el método que se ejecuta una sola vez al cargar el tipo en memoria:

Terminal

monodis UserInfo.exe | grep -A 40 ".cctor"
        

El constructor estático revela el propósito completo del binario: llama a getPassword() para obtener la contraseña en claro, y la usa junto con el usuario support\ldap para autenticarse en LDAP://support.htb mediante System.DirectoryServices.DirectoryEntry. Es decir, UserInfo.exe es una herramienta que consulta el directorio activo usando una cuenta de servicio LDAP cuyas credenciales están embebidas en el propio ejecutable. Para extraer  la contraseña en claro podemos ejecutar el binario en un entorno Windows controlado (o en Wine) con un proxy de red, o bien replicar la lógica de decodificación: decodificar enc_password de Base64 y aplicar el XOR con la clave del código. Al hacerlo  obtenemos la contraseña del usuario ldap: nvEfEK16^1aM4$e7AclUf8x$tRWxPW01%lmz.

Enumeración LDAP Autenticada


Con credenciales válidas para LDAP podemos hacer una consulta completa del directorio activo. El protocolo LDAP permite consultar prácticamente cualquier atributo de cualquier objeto del dominio a cualquier usuario autenticado, incluyendo atributos de descripción que a veces contienen información sensible. Usamos netexec con el módulo LDAP para volcar todos los usuarios junto con sus atributos sAMAccountName e info (campo de descripción):

Terminal

nxc ldap 10.129.47.81 -u ldap \ -p "nvEfEK16^1aM4$e7AclUf8x$tRWxPW01%lmz" \ --query "(objectClass=user)" "sAMAccountName info"
        


Entre los usuarios listados (Administrator, Guest, krbtgt, ldap, smith.rosario, hernandez.stanley, wilson.shelby, anderson.damian, thomas.raphael, levine.leopoldo) uno destaca inmediatamente: el usuario support tiene en su campo info la cadena Ironside47pleasure40Watchful. Esto es una práctica insegura frecuente en entornos corporativos mal gestionados: administradores que guardan contraseñas temporales o notas en los campos de descripción de los objetos del AD, sin considerar que esos campos son visibles para cualquier  usuario autenticado del dominio. Las credenciales obtenidas son: support : Ironside47pleasure40Watchful.

Acceso Inicial — WinRM


Teniendo credenciales del usuario support, el siguiente paso es determinar qué acceso nos proporcionan. Recordando que el puerto 5985 (WinRM) estaba abierto desde el reconocimiento inicial, verificamos si este usuario pertenece al grupo Remote Management Users, que es el requisito para acceder via WinRM:

Terminal

nxc winrm 10.129.47.81 -u support -p 'Ironside47pleasure40Watchful' -x 'whoami'
        


La etiqueta (Pwn3d!) en el output de netexec confirma que el usuario tiene acceso WinRM y que el comando se ejecutó correctamente. El resultado de whoami muestra support\support, confirmando que estamos operando como ese usuario dentro del Domain Controller. Leemos el flag de usuario:

Terminal

nxc winrm 10.129.47.81 -u support -p 'Ironside47pleasure40Watchful' \ -x 'type C:\Users\support\Desktop\user.txt'
        


Con acceso como support tenemos foothold en el DC, pero con privilegios limitados. El siguiente objetivo es escalar a Administrator o SYSTEM. Para eso necesitamos entender qué permisos especiales tiene esta cuenta en el entorno del AD.


Enumeración de ACLs — BloodHound


La escalada de privilegios en entornos de Active Directory rara vez depende de vulnerabilidades del sistema operativo; habitualmente se aprovechan  relaciones de confianza mal configuradas entre objetos del AD: grupos, permisos sobre objetos, delegaciones. La herramienta estándar para mapear estas relaciones es BloodHound, que recolecta información del AD y la representa como un grafo  orientado donde los nodos son objetos (usuarios, grupos, equipos) y las aristas son permisos. Ejecutamos el colector desde nuestra máquina atacante:

Terminal

bloodhound-python -u support \ -p 'Ironside47pleasure40Watchful' \ -d support.htb -ns 10.129.47.81 -c All
        

bloodhound-python recolecta usuarios, grupos, equipos, GPOs, sesiones y ACLs del dominio sin necesidad de ejecutar nada en el DC. Los resultados se guardan en archivos JSON que luego importamos a la interfaz gráfica de BloodHound para visualizar los paths de ataque.

En BloodHound, marcamos la cuenta support como "owned" (comprometida) y usamos la query "Shortest Paths from Owned Principals to Domain Admins" para ver qué caminos existen hacia privilegios de dominio. El grafo revela lo siguiente:


El usuario support es miembro del grupo Shared Support Accounts. Ese grupo tiene el permiso GenericAll sobre el objeto DC$ (la cuenta de equipo del Domain Controller). GenericAll es el permiso más amplio posible en AD: equivale a control total sobre el objeto. Esto incluye la capacidad de modificar el atributo msDS-AllowedToActOnBehalfOfOtherIdentity del DC, que es exactamente el atributo que controla la delegación basada en recursos (RBCD).


Este hallazgo es la pieza que justifica toda la fase de escalada: no estamos explotando una vulnerabilidad del sistema operativo, sino una configuración errónea de permisos en el AD que nos otorga el control necesario para ejecutar el ataque RBCD.


Escalada de Privilegios — Ataque RBCD


Resource-Based Constrained Delegation (RBCD) es un mecanismo de Kerberos que permite que un servicio B obtenga tickets de servicio en nombre de cualquier usuario para acceder a un servicio A, siempre que el objeto de A tenga al objeto de B listado en su atributo msDS-AllowedToActOnBehalfOfOtherIdentity. En términos simples: si controlamos ese atributo en el DC, podemos hacer que una cuenta que nosotros  controlemos pueda impersonar a Administrator frente al DC. El ataque requiere cuatro pasos.


Crear una machine account bajo nuestro control

El ataque RBCD requiere que el objeto autorizado sea una cuenta con Service Principal Names (SPNs). Las machine accounts los tienen por defecto. Por defecto en AD, cualquier usuario autenticado puede crear hasta 10 computer accounts en el dominio (controlado por el atributo ms-DS-MachineAccountQuota, cuyo valor por  defecto es 10). Creamos la cuenta VigiaDC$ con una contraseña conocida por nosotros:

Terminal

nxc ldap 10.129.47.81 -u support -p 'Ironside47pleasure40Watchful' \ -M add-computer -o NAME='VigiaDC$' PASSWORD='VigiaPass123!'
        


La confirmación "Successfully added VigiaDC$ with password VigiaPass123!" indica que la cuenta fue creada. A partir de este momento tenemos una machine account en el dominio support.htb cuyas credenciales conocemos por completo.


Configurar la delegación RBCD sobre el DC

Ahora usamos el permiso GenericAll que support tiene sobre DC$ para escribir en el atributo msDS-AllowedToActOnBehalfOfOtherIdentity del DC, autorizando a VigiaDC$ a actuar en delegación. Lo hacemos con bloodyAD, que simplifica la manipulación de atributos del AD desde Linux:

Terminal

bloodyAD --host 10.129.47.81 -d support.htb \ -u support -p 'Ironside47pleasure40Watchful' \ add rbcd 'DC$' 'VigiaDC$'
        


Solicitar un ticket Kerberos impersonando a Administrator

Con la delegación configurada, usamos getST.py de Impacket para ejecutar el flujo S4U2Self + S4U2Proxy. El proceso funciona así: primero getST.py obtiene un TGT (Ticket Granting Ticket) para VigiaDC$ usando sus credenciales. Luego solicita un ST (Service Ticket) via S4U2Self, que es un mecanismo que permite a una cuenta obtener un ticket de servicio para sí misma en nombre de otro usuario (Administrator en este caso), sin que ese usuario haya iniciado sesión. Finalmente, via S4U2Proxy, canjea ese ticket por uno válido para el servicio  cifs/DC.support.htb impersonando a Administrator. El ticket resultante se guarda en un archivo .ccache en formato estándar de Kerberos:

Terminal

python3 getST.py \ -spn cifs/DC.support.htb \ -impersonate Administrator \ -dc-ip 10.129.47.81 \ 'support.htb/VigiaDC$:VigiaPass123!'
        


El output muestra el flujo completo: Getting TGT for user, Impersonating Administrator, Requesting S4U2self, Requesting S4U2Proxy, y finalmente Saving ticket in Administrator.ccache. Tenemos en nuestra máquina un ticket de Kerberos válido que autentica como Administrator frente al servicio CIFS del DC.


Acceso como SYSTEM con psexec

psexec.py de Impacket puede usar directamente el archivo .ccache como mecanismo de autenticación cuando se le pasan las flags -k (usar Kerberos) y

-no-pass (no pedir contraseña). La variable de entorno KRB5CCNAME indica a las librerías de Kerberos dónde encontrar el ticket:

Terminal

export KRB5CCNAME=Administrator.ccache
        


Terminal

python3 psexec.py -k -no-pass \ [email protected] \
-target-ip 10.129.47.81
        


psexec.py sube un ejecutable temporal al share ADMIN$, crea un servicio temporal en el DC y nos entrega una shell interactiva corriendo como NT AUTHORITY\SYSTEM, el nivel de privilegio más alto posible en Windows. Leemos el flag de root:

Terminal

type C:\Users\Administrator\Desktop\root.txt
        


Resumen y Lecciones de Seguridad


La máquina Support ilustra una cadena de ataque realista donde ningún paso requiere explotar una vulnerabilidad CVE: todo el compromiso se deriva de malas configuraciones y malas prácticas de gestión.

  • SMB sin autenticación. El share support-tools era legible sin credenciales. Todo share en un DC debe requerir autenticación. Auditar regularmente con: net share y revisar las ACLs de cada share.
  • Credenciales en binarios .NET. Los binarios .NET son trivialmente descompilables. Nunca hardcodear credenciales en código. Usar Windows Credential Manager, DPAPI, Azure Key Vault o variables de entorno inyectadas en tiempo de ejecución.
  • Contraseñas en campos de descripción del AD. El campo info/description de un objeto del AD es visible para cualquier usuario autenticado del dominio. Es un vector de enumeración clásico. Auditar con: Get-ADUser -Filter * -Properties Description | Where-Object {$_.Description -ne $null}.
  • MachineAccountQuota > 0. El valor por defecto de ms-DS-MachineAccountQuota
  • (10) permite a cualquier usuario crear cuentas de equipo, lo que es un prerrequisito habitual de ataques RBCD y otros. En entornos productivos debe establecerse en 0 y delegar la creación de cuentas de equipo solo a administradores.
  • GenericAll sobre objetos de equipo críticos. El grupo Shared Support Accounts tenía GenericAll sobre DC$. Los permisos sobre objetos de equipo en AD, especialmente los DCs, deben revisarse periódicamente con BloodHound o PowerView. Una cuenta de soporte no debería tener control total sobre el Domain Controller.
en CTF