HTB: Resolute · de RPC anónimo a Domain Admin vía DnsAdmins
Resumen
Resolute es una máquina Windows retirada de dificultad media de Hack The Box, merece la pena documentarla porque cada paso corresponde directamente a una mala configuración que te encuentras en entornos de AD reales, no a un CTF artificial. El camino es:
- Enumeración RPC anónima que filtra la lista completa de usuarios y una contraseña guardada en el campo de descripción de una cuenta.
- Password spraying de esa credencial contra todo el dominio, que da acceso a otro usuario (
melanie). - Una credencial en texto plano en un transcript de PowerShell que permite el movimiento lateral a
ryan. ryanes miembro de DnsAdmins, que permite cargar una DLL arbitraria en el servicio DNS, que se ejecuta como SYSTEM en el Controlador de Dominio.
Objetivo: 10.129.96.155, un Controlador de Dominio Windows Server 2016 del dominio megabank.local.
Enumeración
Empezamos con un escaneo completo de puertos TCP, más scripts por defecto y detección de versiones:
| |
| |
El fingerprint no deja ninguna dudas: Kerberos (88), LDAP (389/3268), SMB (445), DNS (53) y WinRM (5985) todos abiertos. Es un Controlador de Dominio. Que WinRM esté abierto conviene apuntarlo pronto, si conseguimos credenciales válidas de un usuario del grupo Remote Management Users, tenemos shell interactivo.
Por qué comprobar el acceso anónimo primero
Antes de tirar de exploits o de fuerza bruta, lo primero en un objetivo de AD debería de ser saber si hay acceso anónimo o sesión nula. Es una de las malas configuraciones más comunes en el mundo real, y muy a menudo filtra usuarios, shares y, como veremos, contraseñas. enum4linux-ng agrupa varias técnicas de enumeración SMB/RPC en una sola ejecución:
| |
Saltan dos cosas. Primero, la sesión nula RPC está permitida:
| |
Segundo, esa sesión nula basta para volcar los 27 usuarios del dominio, y uno de ellos tiene una contraseña escrita en texto plano en su descripción:
| |
Es un hallazgo de manual. Alguien en IT dio una contraseña temporal de alta y la dejó en un sitio que cualquier usuario no autenticado de la red puede leer.
La política de contraseñas del dominio también merece atención:
| |
Sin umbral de bloqueo de cuenta, podemos probar contraseñas contra muchas cuentas sin riesgo de bloquear a nadie. Eso hace seguro el siguiente paso.
Punto de entrada
Welcome123! no funciona directamente para marko:
| |
Es lo esperable, las contraseñas de alta como esta suelen reutilizarse en varias cuentas nuevas, no solo en una. Así que en vez de probar uno por uno, la probamos contra la lista completa de usuarios. Esto es password spraying: una contraseña, muchos usuarios (lo contrario de fuerza bruta), que es precisamente por lo que importa que no haya política de bloqueo.
| |
| |
Un acierto: melanie. Está en Remote Management Users, así que tenemos WinRM disponible:
| |
| |
Flag de usuario capturada.
Movimiento lateral a ryan
melanie no tiene nada interesante en cuanto a privilegios (whoami /all solo muestra grupos por defecto), y su directorio personal no tiene historial de PowerShell. La carpeta C:\Users muestra un perfil Administrator y otro ryan que no podemos leer directamente.
La pista llega al listar la raíz de C:\ con -Force, para revelar carpetas ocultas:
| |
| |
PSTranscripts no es una carpeta estándar de Windows, está oculta y se añadió a mano. La transcripción de PowerShell registra sesiones enteras de consola, comandos incluidos. Al escarbar (las subcarpetas también están ocultas, así que -Recurse -Force):
| |
Dentro del transcript, ryan había ejecutado un comando net use con su contraseña en la propia línea, capturada literalmente por la transcripción:
| |
Segundo hallazgo de manual: transcripción de PowerShell habilitada sin proteger el directorio de transcripts, exponiendo una credencial en texto plano a cualquier usuario que pueda leer los logs.
La credencial es válida, y ryan también está en Remote Management Users:
| |
Escalada de privilegios · DnsAdmins a SYSTEM
Al comprobar los grupos de ryan aparece la clave:
| |
| |
ryan es miembro de DnsAdmins. Es una debilidad de diseño muy conocida de Active Directory (documentada públicamente desde 2017): el servicio DNS de Windows corre como SYSTEM en el Controlador de Dominio, y los miembros de DnsAdmins pueden configurarlo para cargar una “plugin DLL a nivel de servidor” mediante el ajuste serverlevelplugindll sin necesidad de ser admin local. Cuando el servicio DNS se reinicia, carga nuestra DLL y ejecuta su código como SYSTEM.
Construir una DLL que evada Defender
El enfoque evidente, msfvenom -p windows/x64/exec ... -f dll, genera una DLL cuyo shellcode detecta y bloquea silenciosamente el Windows Defender que corre en la máquina. La solución es compilar nosotros una DLL sencilla en C; al no contener shellcode reconocible, pasa por delante de la detección por firmas:
| |
| |
Una nota sobre la elección del payload: esta máquina ejecuta una tarea de limpieza que revierte los cambios periódicamente (añadir ryan a Domain Admins funcionó, pero la pertenencia al grupo (y el propio valor del registro) se reseteaban en un par de minutos). En vez de pelear contra esa carrera, la DLL simplemente exfiltra el flag directamente a un share SMB. Como el fichero aterriza en la máquina atacante en el instante en que se ejecuta la DLL, la limpieza de la máquina da igual.
Servir la DLL
Alojamos la DLL por SMB para que el DC la descargue. Detalle importante: no compartas todo tu directorio personal. Un montaje .gvfs dentro de él rompe el manejo de peticiones de impacket y sabotea silenciosamente la entrega de la DLL. Usa una carpeta limpia con solo la DLL:
| |
Disparar la carga
Desde la sesión WinRM de ryan, apuntamos el servicio DNS a la DLL y lo reiniciamos:
| |
Un detalle que me costó tiempo: el servicio DNS solo intenta cargar el plugin cuando el valor del registro cambia. Si ya está puesto a la misma ruta (o la tarea de limpieza acaba de borrarlo), un simple reinicio no vuelve a disparar la carga, así que hay que asegurarse de que el valor cambie de verdad antes de reiniciar.
El servidor SMB registra al DC conectándose como RESOLUTE$ (la cuenta de máquina, es decir SYSTEM) y descargando la DLL. De vuelta en la máquina de ataque:
| |
Flag de root capturada. Compromiso total del dominio.
Lecciones
Resolute es valiosa precisamente porque ninguno de sus pasos es exótico, son los errores que aparecen una y otra vez en auditorías reales:
- El RPC anónimo / sesión nula debería estar deshabilitado en los controladores de dominio; le entrega gratis toda tu lista de usuarios a un atacante.
- Nunca guardes contraseñas en atributos de AD como el campo de descripción, son legibles por cualquier usuario autenticado (aquí, incluso no autenticado).
- La reutilización de contraseñas de alta convierte una credencial filtrada en un punto de entrada; las contraseñas temporales deben ser únicas y forzar el cambio en el primer inicio de sesión.
- La transcripción de PowerShell es un buen control defensivo, pero el directorio de transcripts debe estar protegido, o se convierte en un almacén de credenciales para el atacante.
- DnsAdmins equivale a Domain Admin en un DC. Trata la pertenencia como tier-0 y audítala.
Los flags están parcialmente ocultos, por convención.
También redacté este ejercicio como un informe de test de intrusión formal, el mismo formato que entregaría a un cliente, con resumen ejecutivo, hallazgos puntuados con CVSS y guía de remediación.