desktopVintage

Vintage es una máquina Windows con grandes dificultades diseñada en torno a un supuesto escenario de violación, en el que al atacante se le proporcionan credenciales de usuario con pocos privilegios. La máquina cuenta con un entorno Active Directory sin ADCS instalado, y la autenticación NTLM está deshabilitada. Hay una "Pre2k Computer created," lo que significa que la contraseña es la misma que el sAMAccountName de la cuenta de la máquina. La "Domain Computer" unidad organizativa (OU) tiene una configuración que permite a los atacantes leer la contraseña de la cuenta de servicio, que tiene gMSA configurado. Tras obtener la contraseña, la cuenta de servicio puede añadirse a un grupo privilegiado. El grupo tiene control total sobre un usuario deshabilitado. El atacante debe restaurar el usuario deshabilitado y configurar un Service Principal Name (SPN) para realizar Kerberoasting. Después de recuperar la contraseña, la cuenta de usuario ha reutilizado la misma contraseña. El nuevo usuario comprometido tiene una contraseña almacenada en el Gestor de Credenciales. El usuario puede agregarse a otro grupo privilegiado configurado para la Delegación Restringida Basada en Recursos (RBCD) en el Controlador de Dominio, lo que permite al atacante comprometerlo.


Reconnaissance

Para la fase de reconocimiento inicial de la máquina Vintage utilizamos nuestra herramienta personalizada iReconarrow-up-right. Esta herramienta automatiza un escaneo Nmap completo que incluye:

  1. Detección de puertos TCP abiertos (-p- --open).

  2. Escaneo de versiones (-sV).

  3. Ejecución de scripts NSE típicos para enumeración adicional (-sC).

  4. Exportación del resultado en XML y conversión a HTML para facilitar su lectura.

Para empezar, exportaremos en una variable de entorno llamada IP la dirección IP de la máquina objetivo, lanzaremos la herramienta de iRecon proporcionándole la variable de entorno.

Resumen de Puertos Abiertos

En la enumeración de puertos encontramos importantes como los siguientes:

Puerto
Servicio

88

Kerberos

445

SMB

389

LDAP

636

LDAPS

5985

WinRM

Por los puertos encontrados, parece que nos estamos enfrentando a un Domain Controller (DC) de Windows.

A través de la herramienta de netexec y ldapsearch enumeraremos el equipo para localizar más información. Entre la información obtenida, verificamos el hostname, versión del SO y el nombre del dominio.

triangle-exclamation

En nuestro archivo /etc/hosts añadiremos las siguientes entradas correspondientes para que a la hora de hacer referencia al dominio, hostname o FQDN (nombre de dominio completo que identifica de forma única una máquina o servidor en una red).


NTLM is disabled? Protected users? Testing Kerberos authentication

circle-info

En algunas máquinas de HTB, a veces se nos proporcionan credenciales iniciales como en este caso.

Al intentar validar las credenciales que se nos proporcionan por parte de HTB, observamos el mensaje de STATUS_NOT_SUPPORTED. Esto parece indicar que la autenticación por NTLM, es decir usuario y contraseña, está protegida o deshabilitada.

En nuestro segundo intento de autenticarnos mediante Kerberos con el parámetro (-k) nos aparecía el siguiente mensaje de error: KRB_AP_ERR_SKEW.

circle-info

KRB_AP_ERR_SKEW es un error de autenticación de Kerberos que indica que la diferencia de tiempo entre el cliente y el servidor (Centro de Distribución de Claves - KDC) es demasiado grande. La autenticación Kerberos falla con este error porque el protocolo requiere que los tiempos del cliente y del servidor estén sincronizados para evitar ataques de repetición.

triangle-exclamation

Para solucionar el problema sincronizaremos la hora a través de ntpdate. Una vez sincronizada nuestra hora con el KDC, al volver a intentar autenticarnos mediante Kerberos (-k), verificamos que nos valida correctamente la autenticación.

En este momento, sacamos en conclusión los siguientes puntos importantes de cara a la continuación de la máquina:

  1. Parece que la autenticación NTLM está protegida/deshabilitada. Quizás solamente algún usuario se encuentre en algún grupo como Protected Users o directamente tengamos que autenticarnos siempre por Kerberos y no por NTLM.

  2. Para autenticarnos mediante Kerberos, deberemos de solicitar un TGT (Ticket Granting Ticket) de la cuenta que obtengamos.

  3. Configurar correctamente nuestra máquina atacante para trabajar correctamente con Kerberos y no tener los típicos problemas de que no encuentra el server, errores como hemos visto de la hora, etc.

  4. Seguramente tengamos que sincronizar nuestra hora con el KDC mediante ntpdate.

triangle-exclamation

Tendremos que configurar nuestro archivo /etc/krb5.conf con el siguiente contenido, para que así a la hora de autenticarnos mediante Kerberos, pueda encontrar el KDC (Key Distribution Center), que normalmente es el Domain Controller.

A través de la herramienta de impacket-getTGT solicitaremos un TGT (Ticket Granting Ticket) del usuario P.Rosa@vintage.htb. Este comando nos generará un ticket en format .ccache el cual deberemos de exportar en la variable KRB5CCNAME para poder hacer uso del TGT correctamente.

A través de la utilidad de klist verificaremos que nuestro TGT es válido y se encuentra funcionando correctamente.

triangle-exclamation

SMB Enumeration

Crearemos una variable de entorno llamada FQDNen la cual su valor sea el FQDN del Domain Controller de la máquina objetivo, que en este caso, es dc01.vintage.htb.

Para utilizar el Ticket Granting Ticket (TGT) que hemos solicitado en el punto anterior y almacenado en KRB5CCNAME, en NetExec tenemos el parámetro (--use-kcache) para utilizar nuestro TGT (.ccache).

Realizaremos una enumeración del servicio SMB en el cual nos encontramos que tenemos permisos de READ sobre los siguientes recursos compartidos: IPC$, NETLOGON y SYSVOL. De momento nada interesante que podamos obtener.

circle-info

Cuando trabajamos con Kerberos, es fundamental utilizar el FQDN (Fully Qualified Domain Name) en lugar de la dirección IP. Esto se debe a que Kerberos no se basa en IPs, sino en nombres de servicio (SPN, Service Principal Names), los cuales están estrechamente ligados al nombre completo del host dentro del dominio.

Al usar el FQDN, el cliente puede construir correctamente el SPN necesario para solicitar un ticket de servicio (TGS) al KDC. Si en cambio usamos una IP, el cliente no puede asociarla con ningún SPN válido, lo que provoca errores de autenticación o directamente un fallback a otro mecanismo como NTLM.

Por eso, para que el proceso de autenticación Kerberos funcione correctamente, siempre es necesario referirse a los servicios utilizando su FQDN, como por ejemplo dc01.vintage.htb, y no simplemente 10.10.11.45.


Users Enumeration

Para enumerar los usuarios del dominio, usamos NetExec con el protocolo LDAP (puerto 389). Aprovechamos el TGT que ya tenemos en caché en la variable KRB5CCNAME con el parámetro (--use-kcache), y le indicamos (--users) para que nos liste los usuarios disponibles. Además, muchas veces se muestran las descripciones, donde a veces aparece info útil como posibles credenciales o roles.

La salida nos confirma que se han enumerado correctamente los usuarios del dominio vintage.htb, incluyendo nombres como Administrator, Guest, krbtgt y M.Rossi. En algunos casos, también podemos ver la fecha del último cambio de contraseña y si hubo intentos fallidos de login.

triangle-exclamation

Almacenaremos el resultado del output anterior en un archivo llamado user.txt, el siguiente punto será transformar este resultado para quedarnos solamente con los nombres de usuarios tal y como se muestra a continuación.


Attempting to perform AS-REP Roast and Kerberoasting Attack (FAILED)

Dado que disponemos de un listado potencial de usuarios válidos del dominio, intentamos realizar un AS-REP Roast Attack.

Este ataque consiste en solicitar un TGT (Ticket Granting Ticket) a aquellos usuarios del listado (users.txt) que tengan habilitado el flag DONT_REQ_PREAUTH de Kerberos. Para esto, utilizamos la herramienta GetNPUsers.py de la suite Impacket, que nos permite identificar qué usuarios tienen esa opción activa.

El objetivo es obtener un TGT sin autenticación previa y luego intentar crackear offline la contraseña. Sin embargo, ninguno de los usuarios tenía configurado dicho flag, por lo tanto, no eran susceptibles a AS-REP Roasting.

triangle-exclamation

Por otro lado, dado que ya contamos con credenciales válidas del dominio, intentamos realizar un ataque de Kerberoasting.

Este ataque se basa en solicitar un TGS (Ticket Granting Service) para aquellas cuentas del dominio que tengan asignado un SPN (servicePrincipalName). Para ello, usamos la herramienta GetUserSPNs.py de Impacket, que nos permite identificar usuarios con SPNs asociados y solicitar el TGS correspondiente para luego intentar crackear el hash offline.

En este caso, el ataque tampoco tuvo éxito, ya que no se encontró ningún SPN en el dominio. La herramienta no devolvió ninguna entrada, lo que indica que actualmente ninguna cuenta del dominio tiene un SPN asignado.

triangle-exclamation

BloodHound Enumeration

Después de revisar distintos servicios buscando un vector para escalar privilegios, decidimos hacer una enumeración con BloodHound, una herramienta clave en entornos Active Directory.

Para ello, usamos el recolector bloodhound-python, que nos permite extraer toda la información necesaria del dominio directamente desde nuestra máquina Linux, sin necesidad de acceso interactivo al dominio.

Como se muestra en la salida, la herramienta detectó correctamente el TGT en caché, se conectó al servidor LDAP y recopiló los principales objetos del dominio: usuarios, grupos, equipos, GPOs, OUs, etc. La recolección finalizó exitosamente generando un archivo .zip que luego podemos analizar con la interfaz de BloodHound.

triangle-exclamation

Levantaremos nuestro BloodHound-CE que tenemos instalado previamente a través del siguiente comando,

circle-info

En caso de no tener BloodHound-CE instalado en el equipo, podemos instalarlo desde la siguiente guíaarrow-up-right.

Una vez iniciemos BloodHound-CE y hayamos subido nuestro archivo comprimido .zip, exploraremos la interfaz para enumerar el dominio a través de BloodHound.

Por una parte, nos encontramos que disponemos de 2 Domain Admins del dominio, el usuario Administrator y L.Bianchi_adm.

Por otro lado, al utilizar la opción Shortest path to Domain Admin dentro de BloodHound, identificamos una ruta potencialmente interesante. Este camino nos muestra una cadena de relaciones que podríamos aprovechar si en algún momento logramos obtener acceso al usuario C.Neri_adm.

En este caso, lo que destaca es la presencia del permiso AllowedToAct, lo que sugiere que esta cuenta podría tener capacidad de control remoto sobre otro equipo del dominio. Esto, combinado con otros privilegios del grafo, podría abrirnos una vía clara hacia altos privilegios como Domain Admin.

circle-info

En fases posteriores, si conseguimos credenciales de C.Neri_adm o de otro nodo clave en la ruta, podríamos intentar un ataque de Resource-Based Constrained Delegation (RBCD), aprovechando este ACL.

Durante la enumeración, encontramos un total de tres equipos dentro del dominio:

  • DC01.vintage.htb: el Domain Controller principal.

  • FS01.vintage.htb: un equipo adicional del dominio.

  • GMSA01$@vintage.htb: una cuenta de equipo que parece estar asociada a una gMSA (Group Managed Service Account), lo cual sugiere que podría estar vinculada a tareas automatizadas o servicios gestionados en el dominio.

Este último puede ser relevante si más adelante buscamos obtener la contraseña de la gMSA o identificar sobre qué equipo tiene permisos para actuar.

Buscando otros caminos para escalar privilegios o acceder a nuevas credenciales, encontramos un path interesante en BloodHound.

Si conseguimos credenciales del equipo FS01$, podríamos abusar del permiso ReadGMSAPassword sobre GMSA01$, lo que nos permitiría recuperar su contraseña. A su vez, esta cuenta tiene permisos de AddSelf y GenericWrite, lo cual nos abre otras posibles vías de ataque si podemos usar esos privilegios.

Además, si en algún punto logramos pertenecer al grupo SERVICEMANAGERS, tendríamos permisos de GenericAll sobre tres usuarios (SVC_ARK, SVC_LDAP y SVC_SQL), los cuales podrían ser útiles más adelante para escalar o moverse lateralmente dentro del dominio.


Auth as FS01$

Abusing Pre-Windows 2000 computers (Pre2k)

Investigando cómo podríamos autenticar como el equipo FS01$, notamos que pertenece al grupo PRE-WINDOWS 2000 COMPATIBLE ACCESS, lo cual puede abrir una vía interesante de acceso.

Este grupo está relacionado con equipos configurados como "anteriores a Windows 2000", donde la contraseña por defecto de la cuenta de máquina puede ser predecible. En muchos casos, esta contraseña se genera a partir del nombre del equipo en minúsculas (sin el símbolo $), por ejemplo: fs01.

Esto nos permite intentar autenticarnos con la cuenta FS01$ usando como contraseña el nombre del equipo (fs01), lo cual puede funcionar si la cuenta fue creada manualmente o no ha sido modificada.

circle-info

Una vez logremos autenticarnos como FS01$, podríamos explotar los permisos de ReadGMSAPassword que vimos anteriormente.

Para comprobar si la cuenta del equipo FS01$ sigue usando credenciales por defecto (es decir, el nombre del host en minúsculas sin el $), utilizamos la herramienta pre2k, como explicamos anteriormente.

Esta herramienta permite comprobar si los equipos que forman parte del grupo PRE-WINDOWS 2000 COMPATIBLE ACCESS conservan sus credenciales predeterminadas, lo cual es común si no fueron modificadas desde su creación.

En nuestro caso, generamos un archivo computers.txt con el nombre del equipo y lo pasamos como entrada a la herramienta. Como resultado, confirmamos que las credenciales por defecto funcionan para FS01$.

Esto nos permite autenticarnos como FS01$, lo cual será clave para leer la contraseña del gMSA y avanzar en la ruta indicada anteriormente.

triangle-exclamation

A través de la herramienta getTGT.py de Impacket, podemos solicitar el TGT (Ticket Granting Ticket) para la cuenta de equipo FS01$, lo que nos permitirá autenticarnos a servicios del dominio como si fuéramos dicho equipo.

Una vez obtenido el ticket (.ccache), lo guardamos localmente y configuramos la variable de entorno KRB5CCNAME para usarlo en futuras peticiones. Finalmente, verificamos su validez con la herramienta klist.

triangle-exclamation

Auth as GMSA01$

Abusing ReadGMSAPassword privileges to retrieve gMSA password

Siguiendo el path que habíamos identificado, ahora que tenemos acceso como FS01$, podemos avanzar con el abuso del privilegio ReadGMSAPassword.

Este equipo forma parte del grupo DOMAIN COMPUTERS, cuyos miembros tienen permiso para leer la contraseña del objeto GMSA01$. Gracias a este ACL, tenemos la posibilidad de extraer directamente la contraseña de la gMSA asociada.

Este paso es clave para avanzar en la cadena de explotación, ya que nos permitirá actuar como GMSA01$ y aprovechar sus privilegios dentro del dominio.

Para leer la contraseña de la cuenta gMSA01$, utilizamos la herramienta BloodyAD, esencial para pentesting en entornos Active Directory. Esta herramienta permite tanto enumerar como atacar objetos del dominio.

En este caso, nos autenticamos mediante Kerberos (-k) y solicitamos el atributo msDS-ManagedPassword del objeto GMSA01$, que es donde se almacena su contraseña.

triangle-exclamation

Una vez obtenido el hash NTLM de la cuenta GMSA01$, solicitaremos su TGT (Ticket Granting Ticket) utilizando la herramienta getTGT.py de Impacket.

El ticket generado se guarda en un archivo .ccache, que luego exportamos en la variable KRB5CCNAME para usarlo en futuras autenticaciones. Finalmente, con klist validamos que el TGT esté correctamente cargado.

triangle-exclamation

Shell as C.Neri

Abusing GenericWrite Privilege on a Group to Add Members

Siguiendo el path inicial identificado, ahora que tenemos acceso como GMSA01$, podemos abusar de los permisos GenericWrite y AddSelf que tiene sobre el grupo SERVICEMANAGERS.

Esto nos permite añadir la cuenta GMSA01$ (o cualquier otra) como miembro del grupo. En este caso, optamos por añadir al usuario P.Rosa, que fue el que se nos proporcionó al inicio del pentest. Sin embargo, también podríamos haber añadido a FS01$ o incluso a la propia GMSA01$, ya que disponemos de sus credenciales.

Este paso es clave, ya que formar parte de SERVICEMANAGERS nos otorga privilegios GenericAll sobre varias cuentas del dominio, lo que amplía aún más la superficie de ataque.

Para añadir al usuario P.Rosa al grupo SERVICEMANAGERS, tenemos varias formas de hacerlo mediante autenticación Kerberos.

En nuestro caso, usamos tanto bloodyAD como PowerView.py, ya que ambas permiten realizar esta acción utilizando un TGT en caché.

En ambas herramientas nos conectamos a través de Kerberos mediante el TGT (.ccache) cargado en la variable KRB5CCNAME y añadimos al usuario P.Rosa al grupo mencionado.

triangle-exclamation

Abusing GenericAll privileges to Enable User Accounts, DONT_REQ_PREAUTH & SPNs for AS-REP Roasting & Kerberoasting

En este punto, la usuaria P.Rosa ya forma parte del grupo SERVICEMANAGERS, el cual tiene permisos de GenericAll sobre las siguientes cuentas del dominio:

  • SVC_SQL@vintage.htb

  • SVC_LDAP@vintage.htb

  • SVC_ARK@vintage.htb

Tener GenericAll implica control total sobre esos objetos. Podemos, entre otras cosas:

  • Cambiar sus contraseñas

  • Modificar atributos sensibles (como userAccountControl)

  • Habilitar la opción DONT_REQ_PREAUTH para ataques de AS-REP Roasting

  • Configurar o forzar SPNs para realizar Kerberoasting

  • Habilitar cuentas deshabilitadas

Esto nos da un abanico de opciones para seguir explotando el entorno dependiendo de lo que necesitemos en cada momento.

Revisando las cuentas sobre las que tenemos permisos de GenericAll, notamos que una de ellas —SVC_SQL@vintage.htb— se encuentra deshabilitada.

Como contamos con control total sobre este objeto, podemos habilitar la cuenta fácilmente modificando el atributo userAccountControl, lo cual nos devuelve el acceso total a esa identidad para futuros usos (como login, SPN abuse o AS-REP Roasting si lo activamos).

Enabling users to be susceptible to AS-REP Roast

En este primer caso, explicaremos una manera de realizar esta parte de la máquina Vintage que será habilitando a los usuarios a que dispongan de la flag DONT_REQ_PREAUTH de Kerberos y así sean susceptibles a un AS-REP Roast Attack.

Como hemos comentado anteriormente, disponemos de las herramientas de bloodyAD y PowerView.py en las cuales verificaremos ambas maneras de cómo se utilizan estas herramientas para habilitar el DONT_REQ_PREAUTH y por otro lado, habilitar a un usuario deshabilitado modificando su UAC (userAccountControl).

triangle-exclamation

Para el caso de la herramienta de bloodyAD, la sintaxis para habilitar una cuenta deshabilitada es bastante sencilla. Ya que solamente deberemos remover la flag ACCOUNTDISABLE de la UAC del usuario en cuestión.

Por otro lado, para habilitar que un usuario disponga de la flag DONT_REQ_PREAUTH de Kerberos y volverlo susceptible a AS-REP Roasting, deberemos de añadir una nueva flag DONT_REQ_PREAUTH a la UAC del usuario.

En este punto, ya modificamos correctamente el atributo userAccountControl de los usuarios seleccionados, activando la flag DONT_REQ_PREAUTH de Kerberos. Esto los vuelve vulnerables a un AS-REP Roasting Attack.

En la enumeración inicial, ningún usuario era susceptible, pero ahora al volver a lanzar el ataque con la herramienta GetNPUsers.py de Impacket, obtenemos con éxito los hashes TGT (Ticket Granting Ticket) de los tres usuarios a los que les activamos la flag.

Estos hashes los podemos almacenar en un archivo llamado hashes y posteriormente crackearlos de manera offline con John o Hashcat.

triangle-exclamation

Enabling users to be susceptible to Kerberoasting Attack

En lugar de aplicar la flag DONT_REQ_PREAUTH para realizar un AS-REP Roasting, también podemos hacer que los usuarios sean vulnerables a Kerberoasting asignándoles un SPN (Service Principal Name).

Esto lo haremos usando bloodyAD, PowerView.py y targetedKerberoast.py, siempre autenticándonos vía Kerberos con el TGT cargado en la variable KRB5CCNAME.

triangle-exclamation

Para bloodyAD, la sintaxis es bastante sencilla. En este caso, nos autenticamos mediante Kerberos (-k) y eliminamos la flag ACCOUNTDISABLE del usuario SVC_SQL para asegurarnos de que no esté deshabilitado.

Luego, añadimos un atributo SPN (Service Principal Name) a cada uno de los usuarios. Esto los hace vulnerables a Kerberoasting, ya que al tener un SPN asociado, es posible solicitar su TGS.

Es importante que cada SPN sea distinto, ya que no se puede asignar el mismo SPN a múltiples cuentas dentro del dominio.

En la enumeración inicial de la máquina Vintage, al usar GetUserSPNs.py de Impacket, no obtuvimos resultados porque ningún usuario tenía un SPN (servicePrincipalName) asociado.

Después de asignar un SPN personalizado a cada cuenta, volvimos a ejecutar la herramienta de Impacket y esta vez obtuvimos correctamente los hashes TGS (Ticket Granting Service) de los tres usuarios que hicimos vulnerables a Kerberoasting.

triangle-exclamation

Cracking Hashes with John

Después de obtener los hashes TGT y TGS de los tres usuarios (ya sea mediante AS-REP Roasting o Kerberoasting), los guardamos en un archivo llamado hashes para proceder a crackearlos.

Utilizamos john con la clásica wordlist rockyou.txt y logramos obtener la contraseña del usuario svc_sql@vintage.htb..

circle-info

Nota: Aunque con los permisos de GenericAll podríamos haber cambiado directamente la contraseña o ejecutado otros ataques, optamos por este enfoque para no romper la cadena de autenticación Kerberos y aprovechar el acceso tal como está.


Password Spraying with Kerbrute and NetExec

Al obtener estas credenciales, una de las prácticas más comunes es realizar un Password Spraying para comprobar si la contraseña se reutiliza en otras cuentas del dominio.

Podemos hacerlo con herramientas como Kerbrute, que realiza el spraying vía Kerberos, o con NetExec, utilizando el parámetro (-k) para Kerberos y (--continue-on-success) para que el ataque no se detenga al encontrar una credencial válida.

En el resultado obtenido, comprobamos que las credenciales son válidas para los siguientes usuarios:

  • svc_sql@vintagehtb

  • C.Neri@vintage.htb

triangle-exclamation

Abusing WinRM with Kerberos TGT (Ticket Granting Ticket)

Revisando nuevamente en BloodHound-CE, nos encontramos que el usuario C.Neri@vintage.htb forma parte del grupo Remote Management Users, con lo cual podríamos conectarnos por RDP (Puerto 3389) o WinRM (Puerto 5985). En este caso, la máquina tiene abierto WinRM y intentaremos conectarnos a través de este protocolo.

circle-info

WinRM, o Administración Remota de Windows, es un protocolo que permite gestionar sistemas Windows de forma remota. Para que se entienda fácil: es como el SSH de Windows, una forma de conectarse y administrar remotamente, similar a cómo usamos PuTTY o SSH en Linux.

A través de la herramienta getTGT.py de la suite Impacket, solicitamos un TGT (Ticket Granting Ticket) para autenticarnos como el usuario C.Neri@vintage.htb.

Una vez obtenido el ticket (.ccache), lo exportamos en la variable KRB5CCNAME, y con la utilidad klist verificamos que el TGT se haya cargado correctamente en nuestra sesión.

circle-info

Nota: Tenemos la variable de entorno IP creada anteriormente que tiene como valor: 10.10.11.45

Nos conectamos al Domain Controller (dc01.vintage.htb) usando la herramienta evil-winrm, aprovechando el TGT (.ccache) del usuario C.Neri@vintage.htb previamente obtenido y exportado en la variable KRB5CCNAME.

Verificamos que logramos acceder al DC y obtenemos finalmente la flag user.txt.

circle-info

Para poder conectarnos a WinRM mediante Evil-WinRM a través de la autenticación de Kerberos con el TGT (.ccache), deberemos de tener configurado nuestro sistema correctamente para no tener problemas.

Para ello, podemos seguir la siguiente configuración donde se explica detalladamente. Evil-WinRM Kerberosarrow-up-right.

triangle-exclamation

Auth as C.Neri_adm

Abusing DPAPI Secrets to Move Laterally (impacket-dpapi)

Una vez que conseguimos acceso al Domain Controller, el siguiente objetivo será escalar privilegios y convertirnos finalmente en Domain Admins.

Buscando posibles vectores de escalada, identificamos la opción de abusar de DPAPI (Data Protection API), lo cual puede permitirnos acceder a credenciales protegidas y movernos lateralmente por el dominio.

circle-info

DPAPI (Data Protection API) es una API de Windows que protege datos sensibles como contraseñas y claves mediante criptografía. Su objetivo es asegurar que solo el usuario o equipo autorizado pueda acceder a esa información. Sin embargo, si un atacante tiene acceso al sistema o privilegios elevados, puede extraer o descifrar estos secretos usando herramientas como Mimikatz o Impacket.

Esto se convierte en un vector de escalación de privilegios, ya que los secretos protegidos pueden contener credenciales que permiten el acceso a otras cuentas o servicios.

En las siguientes rutas es donde se suelen almacenar las credenciales protegidas por DPAPI.

circle-info

C:\Users$USER\AppData\Local\Microsoft\Credentials C:\Users$USER\AppData\Roaming\Microsoft\Credentials\

En el caso del usuario C.Neri, dispone de una credencial llamada C4BB96844A5C9DD45D5B6A9859252BA6 ubicada en C:\Users\C.Neri\AppData\Roaming\Microsoft\Credentials.

Esta credencial se encuentra oculta, para poder descargala a través del módulo download que ofrece evil-winrm, deberemos de quitarle el atributo Hidden y System. Seguidamente, nos dejará realizar el la descarga del archivo en nuestro equipo local.

Las credenciales protegidas por DPAPI están cifradas utilizando una Master Key específica del usuario, derivada de su contraseña.

Estas Master Keys suelen almacenarse en la siguiente ruta:

circle-info

C:\Users$USER\AppData\Roaming\Microsoft\Protect$SUID$GUID

En nuestro caso, encontramos dos posibles Master Keys en esa ubicación. Sabemos que una de ellas es la que se utiliza para proteger la credencial que descargamos anteriormente.

Herramientas como Mimikatz o winPEAS permiten identificar directamente qué Master Key corresponde a cada secreto, pero en este caso lo hicimos manualmente probando ambas, y determinamos que la correcta era: 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b.

Dado que tiene los atributos Hidden y System, se los quitaremos a través de attrib -h -s y podremos descargar la master key a través del módulo download de evil-winrm.

A continuación, el siguiente paso será descifrar la credencial protegida por DPAPI utilizando la herramienta dpapi.py de la suite Impacket.

El primer paso consiste en descifrar la Master Key. Para ello, necesitaremos:

  • El archivo de la Master Key descargado previamente.

  • El SID (Security Identifier) del usuario, que podemos obtener de la ruta donde estaba almacenada la Master Key.

  • La contraseña del usuario propietario de esas credenciales protegidas por DPAPI, en este caso, el usuario C.Neri ya que estamos trabajando en local con los archivos.

Finalmente logramos desencriptar la Master Key con éxito.

Para finalizar, vamos a descifrar la credencial protegida por DPAPI utilizando la Master Key que recuperamos en el paso anterior.

Para ello necesitaremos:

  • El archivo de la credencial protegida que descargamos previamente (C4BB96844A5C9DD45D5B6A9859252BA6).

  • La Master Key desencriptada.

En la salida obtenemos lo que parece ser un nuevo conjunto de credenciales, correspondientes al usuario c.neri_adm@vintage.htb, junto con su contraseña.

Probamos las nuevas credenciales obtenidas para el usuario c.neri_adm@vintage.htb utilizando la herramienta NetExec (nxc) contra el servicio LDAP, autenticándonos mediante Kerberos.

En el resultado comprobamos que las credenciales son válidas, confirmando así que tenemos acceso como c.neri_adm dentro del dominio y podemos seguir avanzando.

triangle-exclamation

Shell as L.Bianchi_adm (Domain Admin)

Finding an entry vector to elevate our privileges with BloodHound

Revisamos nuevamente en BloodHound-CE qué opciones tenemos con el usuario c.neri_adm@vintage.htb, que es el que disponemos actualmente.

Verificamos que este usuario forma parte del grupo Remote Desktop Users, lo que nos permitiría conectarnos directamente al Domain Controller (dc01.vintage.htb) mediante WinRM, y además comprobamos que también pertenece al grupo DELEGATEDADMINS, grupo que investigaremos a continuación para ver si podemos sacarle algún provecho en cuanto a privilegios o delegaciones configuradas.

Por otro lado, también verificamos que el usuario c.neri_adm@vintage.htb dispone de permisos de ACL sobre el grupo DELEGATEDADMINS, concretamente los privilegios de AddSelf y GenericWrite.

Gracias a estos permisos, el usuario tiene la capacidad de añadirse a sí mismo o añadir a cualquier otro usuario al grupo mencionado.

También comprobamos que hay dos miembros que forman parte del grupo DELEGATEDADMINS: el usuario que disponemos actualmente c.neri_adm@vintage.htb y otro nuevo llamado l.bianchi_adm@vintage.htb.

Este segundo usuario pertenece además al grupo DOMAIN ADMINS, por lo que se trata de un Administrador del Dominio.

Esta información nos resulta bastante útil, ya que si bien no podemos acceder directamente al usuario Administrator, podríamos apuntar a este otro objetivo que también tiene privilegios de Domain Admin, y tratar de comprometerlo a través de la relación que mantiene con el grupo DELEGATEDADMINS.

Buscando rutas para elevar nuestro privilegio y lograr convertirnos en Domain Admin, nos encontramos con el siguiente path. Los miembros del grupo DELEGATEDADMINS disponen del privilegio ACL de AllowedToAct, es decir, tienen configurado el atributo msds-AllowedToActOnBehalfOfOtherIdentity sobre el controlador de dominio DC01.VINTAGE.HTB. Esto nos permitiría realizar un ataque de Resource-Based Constrained Delegation (RBCD) y suplantar a un Domain Admin.

Para que este ataque funcione correctamente, debemos tener en cuenta lo siguiente:

  1. Los usuarios que queramos suplantar no deben pertenecer al grupo Protected Users ni tener restricciones de delegación aplicadas.

  2. El usuario que añadimos al atributo msDS-AllowedToActOnBehalfOfOtherIdentity debe tener un SPN (Service Principal Name) configurado, ya que el proceso de S4U2self y S4U2proxy requiere un servicio válido asociado al usuario.

En este punto, el objetivo es conseguir una cuenta que tenga un SPN ficticio para poder realizar el RBCD Attack e impersonar al Domain Admin l.bianchi_adm@vintage.htb.

Si revisamos los usuarios de los que ya disponemos credenciales:

  • P.Rosa → lo añadimos previamente al grupo SERVICEMANAGERS@vintage.htb y tenemos sus credenciales.

  • svc_sql → tenemos sus credenciales y control total sobre él formando parte del grupo SERVICEMANAGERS@vintage.htb .

  • C.Neri → solo disponemos de su contraseña.

  • C.Neri_adm → forma parte de DELEGATEDADMINS y puede añadir usuarios a ese grupo.

Teniendo esto en cuenta, la estrategia es añadir primero al usuario svc_sql al grupo DELEGATEDADMINS, ya que solo los miembros de este grupo tienen el permiso AllowedToAct sobre el DC. Una vez añadido, aprovecharemos que P.Rosa tiene control total sobre svc_sql para asignarle un SPN ficticio, dejándolo preparado para ejecutar el ataque de RBCD.

Con todo esto en cuenta, ya tenemos el escenario listo para ejecutar el ataque de RBCD.


Abusing AllowedToAct privileges (Resource-based Constrained Delegation [RBCD Attack] through SVC_SQL user) with impacket-getST

triangle-exclamation

Añadir al usuario SVC_SQL al grupo DELEGATEDADMINS

El objetivo en este punto es añadir al usuario svc_sql@vintage.htb al grupo DELEGATEDADMINS, para que así herede el permiso AllowedToAct sobre el Domain Controller y podamos ejecutar el ataque de RBCD.

Para ello, el primer paso será solicitar el TGT (Ticket Granting Ticket) del usuario c.neri_adm@vintage.htb, quien tiene permisos de GenericWrite que nos permitirán añadir usuarios al grupo DELEGATEDADMINS. Usaremos la herramienta getTGT.py de Impacket para obtener su TGT en formato .ccache, lo exportaremos con la variable KRB5CCNAME y verificaremos con klist que se haya cargado correctamente en la sesión.

triangle-exclamation

Para añadir al usuario svc_sql@vintage.htb al grupo DELEGATEDADMINS, tenemos varias formas de hacerlo mediante autenticación Kerberos.

En nuestro caso, usamos tanto bloodyAD como PowerView.py, ya que ambas permiten realizar esta acción utilizando un TGT en caché.

En ambas herramientas nos conectamos a través de Kerberos mediante el TGT (.ccache) cargado en la variable KRB5CCNAME y añadimos al usuario SVC_SQL al grupo mencionado.

triangle-exclamation

Añadir al usuario P.ROSA al grupo SERVICEMANAGERS

Como comentamos al inicio, es posible que los permisos y cambios aplicados anteriormente se hayan reseteado. Por eso, vamos a repetir el proceso paso a paso para evitar problemas.

Volveremos a añadir al usuario P.Rosa@vintage.htb al grupo SERVICEMANAGERS. Para ello, primero solicitaremos el TGT (Ticket Granting Ticket) de la cuenta GMSA01$ utilizando la herramienta getTGT.py de la suite Impacket.

El TGT se almacenará en un archivo .ccache, que luego exportaremos en la variable KRB5CCNAME para poder usarlo en futuras autenticaciones. Finalmente, validaremos con klist que el TGT esté cargado correctamente.

triangle-exclamation

Para añadir al usuario P.Rosa al grupo SERVICEMANAGERS, tenemos varias formas de hacerlo mediante autenticación Kerberos.

En nuestro caso, usamos tanto bloodyAD como PowerView.py, ya que ambas permiten realizar esta acción utilizando un TGT en caché.

En ambas herramientas nos conectamos a través de Kerberos mediante el TGT (.ccache) cargado en la variable KRB5CCNAME y añadimos al usuario P.Rosa al grupo mencionado.

triangle-exclamation

Asignar un SPN ficticio al usuario SQL_SVC

El siguiente paso será asignar un SPN (Service Principal Name) ficticio al usuario svc_sql. Lo haremos utilizando la cuenta P.Rosa, que acabamos de volver a añadir al grupo SERVICEMANAGERS, ya que este grupo tiene permisos de GenericAll sobre las tres cuentas svc.

Para ello, primero solicitaremos el TGT (Ticket Granting Ticket) del usuario P.Rosa@vintage.htb usando getTGT.py de Impacket. Una vez obtenido el TGT en formato .ccache, lo exportaremos en la variable KRB5CCNAME y validaremos con klist que se haya cargado correctamente en nuestra sesión.

triangle-exclamation

Si bien recordamos, el usuario svc_sql se encontraba deshabilitado, por lo que primero necesitaremos modificar su userAccountControl (UAC) para volver a habilitarlo. Una vez hecho esto, podremos asignarle un SPN ficticio.

Ambas acciones las podemos realizar utilizando bloodyAD o PowerView.py, autenticándonos mediante Kerberos con el TGT (.ccache) que ya tenemos cargado en la variable KRB5CCNAME.

triangle-exclamation

Resource-based Constrained Delegation Attack with SQL_SVC

Una vez en este punto, tenemos el escenario perfecto para llevar a cabo un ataque de Resource-Based Constrained Delegation (RBCD Attack):

  • El usuario svc_sql@vintage.htb forma parte del grupo DELEGATEDADMINS, cuyos miembros tienen permiso ACL de AllowedToAct sobre el Domain Controller.

  • El usuario svc_sql@vintage.htb ya tiene asignado un SPN (Service Principal Name) ficticio, requisito necesario para realizar el ataque.

  • Tenemos un objetivo claro, l.bianchi_adm@vintage.htb, que es miembro de Domain Admins y que queremos suplantar.

Teniendo este escenario listo, el primer paso será solicitar el TGT (Ticket Granting Ticket) del usuario svc_sql@vintage.htb utilizando la herramienta getTGT.py de Impacket.

Una vez solicitado el TGT, obtendremos un archivo .ccache, el cual exportaremos en la variable KRB5CCNAME y validaremos con klist que esté correctamente cargado en nuestra sesión.

triangle-exclamation

Para ejecutar el Resource-Based Constrained Delegation Attack (RBCD), utilizamos la herramienta getST.py de la suite Impacket. El objetivo es obtener un TGS (Ticket Granting Service) suplantando al usuario l.bianchi_adm@vintage.htb para acceder al Domain Controller.

El ataque se basa en el funcionamiento normal de la delegación Kerberos:

  • Primero realizamos un S4U2Self, donde solicitamos un ticket de servicio a nombre del usuario l.bianchi_adm, usando el SPN ficticio que habíamos asignado previamente a svc_sql.

  • Luego realizamos un S4U2Proxy, donde pedimos al KDC que nos permita usar ese ticket para acceder al servicio cifs/dc01.vintage.htb, aprovechando el permiso AllowedToAct que tiene svc_sql sobre el DC.

En el resultado vemos que primero se completa el S4U2Self, luego el S4U2Proxy, y finalmente se guarda el ticket suplantando a l.bianchi_adm en el archivo .ccache.

triangle-exclamation

Exportamos el nuevo .ccache que contiene el TGS de suplantación del usuario l.bianchi_adm, utilizando la variable KRB5CCNAME, y verificamos con klist que el ticket esté correctamente cargado en nuestra sesión.

Una vez confirmado, nos conectamos al Domain Controller dc01.vintage.htb utilizando la herramienta wmiexec.py de Impacket, autenticándonos directamente mediante Kerberos y sin necesidad de introducir contraseña.

La conexión se establece correctamente, obteniendo una shell bajo el contexto de l.bianchi_adm. Desde esta sesión, confirmamos que disponemos de privilegios de Domain Admin y accedemos al escritorio del usuario Administrator, donde logramos obtener finalmente la flag root.txt

triangle-exclamation

Resource-based Constrained Delegation Attack (RBCD Attack) with FS01$

Por otro lado, también podemos realizar este mismo ataque de RBCD utilizando la cuenta FS01$, de la cual disponemos credenciales y que ya tiene un SPN (ServicePrincipalName) asignado por defecto.

El proceso es el mismo: utilizando la cuenta C.Neri_adm, añadimos FS01$ al grupo DELEGATEDADMINS para que disponga del privilegio ACL AllowedToAct.

Solicitamos el TGT (Ticket Granting Ticket) de FS01$ y realizamos el ataque de RBCD mediante la herramienta getST.py de Impacket, autenticándonos con la cuenta FS01$ y logrando suplantar al Domain Admin: L.Bianchi_adm@vintage.htb.

circle-info

Nota: Tenemos la variable de entorno FQDN creada anteriormente que tiene como valor: dc01.vintage.htb y la variable de entorno IP que tiene como valor la dirección IP de Vintage - 10.10.11.45.


Extra: Dumping NTDS.dit to retrieve all NTLM hashes

Ya que disponemos de privilegios de Domain Admin en el dominio vintage.htb a través del usuario l.bianchi_adm@vintage.htb, podemos aprovechar para realizar un ataque de tipo DCSync y extraer todos los hashes NTLM almacenados en el NTDS.dit, que es la base de datos utilizada por Active Directory para guardar toda la información del dominio, incluidas las credenciales de los usuarios.

Esto nos permite tener acceso completo a cualquier cuenta del dominio sin necesidad de conocer sus contraseñas, ya que disponiendo del hash NTLM podemos realizar ataques como Pass-the-Hash (PtH).

triangle-exclamation

Última actualización

¿Te fue útil?