Forest - Hack The Box
El día de hoy vamos a resolver la máquina Forest de Hack The Box. Es una máquina Windows de nivel de dificultad medio en la intrusión, y medio en la escalada de privilegios según figura en la plataforma.
Fase De Reconocimiento
Primeramente vamos a lanzar una traza ICMP para saber si la máquina está activa.
ping -c 1 10.10.10.161
Una vez comprobamos que la máquina está activa (pues nos devuelve una respuesta), podemos también determinar a que tipo de máquina nos estamos enfrentando en base al valor del TTL; en este caso el valor del TTL de la máquina es 127
, por lo que podemos intuir que estamos ante una máquina Windows. Recordemos que algunos de los valores referenciales son los siguientes:
Sistema Operativo (OS) | TTL |
---|---|
Linux | 64 |
Windows | 128 |
Solaris | 254 |
Si nos damos cuenta, en esta ocasión, el valor del TTL es 127
y no 128
como indica la tabla anterior, esto se debe a que en el entorno de máquinas de Hack The Box, no nos comunicamos directamente con la máquina a vulnerar, sino que existe un nodo intermediario, por lo que el TTL disminuye en una unidad.
ping -c 1 10.10.10.161 -R
Posteriormente, vamos a utilizar la herramienta Nmap para determinar que puertos están abiertos, así como identificar la versión y servicios que corren en el activo. Para determinar que puertos están abiertos podemos realizar lo siguiente:
nmap -p- --open -T5 -v -n 10.10.10.161
En caso de que el escaneo tarde demasiado en completar, tenemos esta otra alternativa:
sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.10.161
A continuación se explican los parámetros utilizados en el escaneo de puertos con Nmap:
Parámetro | Explicación |
---|---|
-p- | Escanea todo el rango de puertos (65535 en total) |
--open | Nos indica todos aquellos puertos que están abiertos (o posiblemente abiertos) |
-T5 | La plantilla de temporizado nos permite agilizar nuestro escaneo, este valor puede ir desde 0 hasta 5, cabe aclarar que a mayor sea el valor de la plantilla, “generaremos más ruido”, pero no pasa nada ¿no? Al fin y al cabo estamos practicando en un entorno controlado y aquí somos todos White Hat |
-v | Verbose, reporta lo encontrado por consola |
-n | No aplicar resolución DNS |
-sS | Escaneo TCP SYN |
-min-rate | Emitir paquetes no más lentos que <valor> por segundo |
-vvv | Triple verbose, para obtener mayor información por consola |
-Pn | No aplicar host discovery |
Una vez hemos detectado los puertos que se encuentran abiertos en el activo, podemos pasar a determinar la versión y servicios que corren bajo estos puertos.
nmap -sC -sV -p 53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,47001,49664,49665,49666,49667,49671,49676,49677,49684,49706,49957 10.10.10.161
A continuación se explican los parámetros utilizados en el escaneo de versiones y servicios con Nmap:
Parámetro | Explicación |
---|---|
-sC | Scripts básicos de enumeración |
-sV | Versión y servicios que corren bajo los puertos encontrados |
-p | Especificamos que puertos queremos analizar (los que encontramos abiertos en el paso anterior) |
Basándonos en la información que nos reporta Nmap, podemos darnos cuenta que la máquina víctima tiene abiertos puertos relacionados con DNS
(53), Kerberos authentication
(88), RPC
(135), NetBIOS
(139), LDAP
(389), SMB
(445) y WinRM
(5985). Por lo que podemos intuir nos estamos enfrentando ante un Domain Controller (DC) y nos encontramos en un entorno de Active Directory (AD).
Fase De Explotación
Lo primero que haremos será comprobar si la máquina cuenta con recursos compartidos a nivel de red a través del uso de un null session, pues no contamos con credenciales; para ello podemos hacer uso de herramientas como SMBMap o smbclient, no obstante, no podremos listar nada.
smbmap -H 10.10.10.161
smbclient -N -L 10.10.10.161
Lo siguiente que podemos probar es enumerar el protocolo LDAP
para obtener información sobre usuarios, grupos u otros objetos en el entorno. Para realizar esto, utilizaremos la herramienta ldapsearch
.
Nuestro primer objetivo será identificar el Naming Context, que es el Distinguished Name (DN) que representa el nivel más alto en la jerarquía del Directory Information Tree (DIT) y servirá como base para nuestras consultas. Utilizaremos el siguiente comando:
ldapsearch -x -h 10.10.10.161 -s base namingcontexts
El campo dn se encuentra vacío porque estamos consultando el objeto base del directorio. Los campos namingContexts listan los diferentes Naming Contexts del servidor LDAP. Cada entrada en namingContexts representa una parte distinta del directorio LDAP que puede ser la base de varias búsquedas.
Utilizaremos DC=htb,DC=local
como base de nuestras consultas porque este es el Naming Context principal que representa el dominio htb.local
, incluyendo usuarios, grupos y otros objetos principales. Los demás Naming Contexts (CN=Configuration, CN=Schema, DC=DomainDnsZones, DC=ForestDnsZones) son específicos para configuraciones y esquemas dentro del entorno de AD.
Una vez obtenemos el DN, podemos empezar a realizar consultas específicas o bien, podríamos listar toda la información del LDAP con el siguiente comando:
ldapsearch -x -h 10.10.10.161 -b "dc=htb,dc=local"
Parámetro | Explicación |
---|---|
-x | Simple authentication |
-h | Host |
-s | Search scope |
-b | DN base para la búsqueda |
Podemos comenzar buscando entradas que contengan la clase de objeto user para listar usuarios del sistema.
ldapsearch -x -h 10.10.10.161 -b "dc=htb,dc=local" '(objectClass=user)'
En los campos sAMAccountName de cada usuario, encontraremos sus respectivos nombres de usuario. Con un listado potencial de usuarios en nuestro poder, podríamos considerar un ataque AS-REP Roasting
.
El ataque AS-REP Roasting
explota una debilidad en la autenticación de Kerberos
en entornos de Active Directory. Este ataque comienza enviando un mensaje de solicitud de Authentication Server Request (AS-REQ) al DC para usuarios que están configurados para no requierer preautenticación de Kerberos. Si la cuenta del usuario está configurada de esta manera, el DC nos responderá con un mensaje de Authentication Server Response (AS-REP), que contiene un Ticket Granting Ticket (TGT) emitido por el Key Distribution Center (KDC). Este TGT puede ser vulnerable a ataques de fuerza bruta si la contraseña es débil, permitiéndonos romper la contraseña del usuario sin tener que realizar una autenticación completa. Esta vulnerabilidad se explota debido a que el servidor responde con un mensaje AS-REP en lugar de rechazar la solicitud debido a la falta de preautenticación.
Con esto en mente, en vez de buscar usuario por usuario manualmente, podemos utilizar un one-liner para filtrar y parsear los usuarios directamente.
Podemos refinar aún más la lista de usuarios obtenida para centrarnos exclusivamente en las cuentas relevantes. Las dos primeras cuentas, DefaultAccount y Guest, son creadas por el propio AD (aunque Guest no está habilitada por defecto). Las cuentas que terminan en $ son cuentas de equipos (computer accounts), mientras que la cuenta $331000-VK4ADACQNUCA tiene un formato inusual y podría ser una cuenta de servicio especial o generada automáticamente. Las cuentas que empiezan por SM_ y HealthMailbox están relacionadas con el servicio Microsoft Exchange. Esto nos deja con cinco usuarios potenciales para nuestro análisis.
Lo siguiente que haremos será utilizar el script GetNPUsers
de la suite Impacket
. Para ejecutarlo, necesitamos proporcionar el nombre del dominio del AD al que queremos apuntar. Para configurar esto, editaremos el archivo /etc/hosts
para asegurarnos de que el nombre de dominio se resuelva a la dirección IP correspondiente del servidor.
Con esto hecho, el comando que utilizaremos es el siguiente:
impacket-GetNPUsers htb.local/ -no-pass -userfile archivoListadoUsuarios
Curiosamente, ninguno de los usuarios que hemos obtenido parece ser vulnerable a AS-REP Roasting
. Por lo tanto, procederemos a enumerar otro protocolo que hemos identificado durante nuestro escaneo con Nmap: RPC
.
Haremos uso de rpcclient
, nuevamente utilizando un null session, pues no contamos con credenciales. Verificamos que podemos conectarnos exitosamente, por lo que procederemos a enumerar información adicional. Podríamos listar los grupos dentro del dominio mediante enumdomgroup o, alternativamente, volver a listar los usuarios del dominio mediante enumdomusers.
Podemos observar tres nuevos usuarios que no habíamos detectado cuando enumeramos con ldapsearch. De los cuales nos interesa svc-alfresco
, pues tanto Administrator como krbtgt son creados por el propio AD.
Si recordamos, cuando utilizamos ldapsearch, filtramos usuarios cuya clase de objeto contenga user, y los cinco usuarios que encontramos anteriormente, cumplen con esta condición.
Sin embargo, al investigar un poco más, descubrimos que este “usuario” svc-alfresco
no tiene una clase de objeto definida. Esto probablemente se debe a que pertenece a la Unidad Organizativa (OU) de Cuentas de Servicio (Service Accounts).
Nuevamente, mediante el uso de un one-liner podríamos filtrar y parsear los usuarios, refinar la lista y utilizarla junto a Impacket
para comprobar si este nuevo usuario es vulnerable a AS-REP Roasting
.
Descubrimos que svc-alfresco
es vulnerable a AS-REP Roasting
y obtenemos un hash que procederemos a intentar romper por fuerza bruta utilizando John the Ripper
en conjunto con el diccionario rockyou.txt.
En caso de no contar con la herramienta John the Ripper
instalada, podemos hacer lo siguiente:
sudo apt install john
john --wordlist=/ruta/del/diccionario/rockyou.txt hash
Una vez obtenemos la contraseña del usuario svc-alfresco
, podemos validar la credencial antes de intentar conectarnos a la máquina víctima para asegurarnos de que es correcta. Recordemos que durante nuestro escaneo con Nmap, observamos que el servicio WinRM
(Windows Remote Management) está activo en la máquina víctima; este será el protocolo que utilizaremos para la conexión.
Para validar la credencial, emplearemos CrackMapExec con el siguiente comando:
crackmapexec winrm 10.10.10.161 -u 'svc-alfresco' -p 's3rvice'
Nos damos cuenta de que la credencial no solo es válida, sino también que este usuario pertenece al grupo Remote Management Users, ya que vemos junto al nombre de usuario un mensaje que dice Pwn3d!. Por lo tanto, podemos conectarnos a la máquina víctima mediante Evil-WinRM
.
Procederemos a conectarnos de la siguiente manera:
evil-winrm -i 10.10.10.161 -u 'svc-alfresco' -p 's3rvice'
Escalada De Privilegios
Una vez dentro de la máquina víctima, podemos empezar a recolectar información del Active Directory que nos permita escalar privilegios. Para ello nos ayudaremos de SharpHound
, un recolector de datos para BloodHound
, una herramienta que permite analizar y visualizar relaciones y permisos en un entorno de Active Directory para identificar posibles caminos de escalada de privilegios.
Lo primero que haremos será descargar SharpHound en nuestro equipo. Algo muy cómodo de Evil-WinRM
es que nos permite subir y descargar archivos muy fácilmente. Para ello, ejecutaremos el siguiente comando para subir el archivo SharpHound.ps1
a la máquina víctima:
upload SharpHound.ps1
Una vez subido, importaremos y utilizaremos la función Invoke-BloodHound
para recolectar toda la información necesaria.
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethod All
Esto generará un archivo comprimido con toda la información del AD. Para descargar este archivo a nuestro equipo, utilizaremos el siguiente comando:
download <timestamp>_BloodHound.zip BloodHound.zip
Lo siguiente que haremos será importar el archivo comprimido que generó SharpHound
a BloodHound
. Para ello, en caso de no contar con la herramienta instalada, podemos hacer lo siguiente:
sudo apt install neo4j bloodhound
Neo4j es la base de datos gráfica que BloodHound
utiliza. La arrancaremos de la siguiente manera:
sudo neo4j console
Nos indicará que nos dirijamos a http://localhost:7474/. Para conectarnos a Neo4j por primera vez, las credenciales que introduciremos son las que vienen por defecto:
- Username: neo4j
- Password: neo4j
A continuación, nos solicitará que cambiemos la contraseña; esta será la que utilizaremos para BloodHound
.
Una vez abramos BloodHound
y nos logueemos, en la parte derecha veremos una sección que dice Upload Data. Aquí es donde subiremos nuestro archivo comprimido.
En la barra de búsqueda en la parte superior izquierda, podemos buscar por el usuario que acabamos de comprometer, svc-alfresco
. Podemos hacer clic derecho sobre él y seleccionar Mark User as Owned.
Si nos dirigimos al apartado Analysis, encontraremos una sección Shortest Paths. Dentro de esta sección, seleccionamos Shortest Path from Owned Principals. Al hacer clic, se desplegará un gráfico que ilustra el mejor camino para convertirnos en administrador del sistema.
Podemos observar que svc-alfresco
es miembro del grupo Service Accounts, el cual es miembro del grupo Privileged IT Accounts, que a su vez es miembro del grupo Account Operators. Además, el grupo Account Operators tiene permisos GenericAll sobre el grupo Exchange Windows Permissions, lo que le da control total sobre este grupo. El grupo Exchange Windows Permissions tiene permisos WriteDacl sobre el dominio, lo que permite modificar la lista de control de acceso discrecional (DACL) del dominio.
Vamos por partes, el grupo Account Operators otorga privilegios limitados de creación de cuentas a un usuario. Por lo tanto, el usuario svc-alfresco
puede crear otras cuentas en el dominio. Por otra parte, el grupo Account Operators tiene permisos GenericAll sobre el grupo Exchange Windows Permissions, lo que significa que svc-alfresco
puede modificar los permisos del grupo Exchange Windows Permissions. Finalmente, el grupo Exchange Windows Permissions tiene permisos WriteDacl sobre el dominio. Abusaremos de esto para otorgarnos privilegios de DCSync
.
El ataque DCSync
simula el comportamiento de un Domain Controller y solicita a otros Domain Controllers que repliquen información utilizando el protocolo Directory Replication Service Remote Protocol (MS-DRSR). Debido a que este protocolo es esencial para el funcionamiento de Active Directory, no se lo puede desactivar. Realizando este ataque, podemos replicar la información del dominio y dumpear todos los hashes del mismo.
Dicho todo esto, lo primero que haremos será aprovechar que svc-alfresco
es miembro del grupo Account Operators, y crear un nuevo usuario. Para ello, haremos lo siguiente:
net user nombreDeUsuario contraseña /add /domain
Lo siguiente que haremos será añadir el usuario que acabamos de crear al grupo Exchange Windows Permissions, aprovechando que svc-alfresco
tiene control total sobre este grupo:
Add-ADGroupMember -Identity "Exchange Windows Permissions" -Members "nombreDeUsuario"
También vamos a añadir este usuario al grupo Remote Management Users para que pueda conectarse a través de Evil-WinRM
:
Add-ADGroupMember -Identity "Remote Management Users" -Members "nombreDeUsuario"
Al añadir al usuario al grupo Remote Management Users, evitamos el uso de PSCredentials, que normalmente se utilizan para ejecutar comandos con las credenciales de otro usuario, las cuales, personalmente, me generaban conflictos con PowerView
.
A continuación, cerraremos la sesión actual de Evil-WinRM
y nos conectaremos nuevamente con el usuario recién creado. Una vez conectados como el nuevo usuario, descargaremos en nuestro equipo el script PowerView, que pertenece a PowerSploit
(una colección de scripts en PowerShell). Igual que antes, lo subiremos mediante Evil-WinRM
y posteriormente lo importaremos:
upload PowerView.ps1
Import-Module .\PowerView.ps1
Una vez importado, utilizaremos la función Add-DomainObjectAcl
para otorgar permisos de DCsync
a nuestro usuario recién creado:
Add-DomainObjectAcl -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity nombreDeUsuario -Rights DCSync
Ya con permisos de DCsync
en nuestro usuario, podemos utilizar secretsdump
, otro script de la suite Impacket
que nos permitirá dumpear los hashes de todos los usuarios del dominio:
impacket-secretsdump htb.local/nombreDeUsuario:contraseña@10.10.10.161
Finalmente, podemos realizar un ataque de tipo Pass the Hash
, que consiste en usar el hash que acabamos de conseguir en lugar de la contraseña (que no conocemos) para autenticarnos. Para esto, podríamos utilizar psexec
(otro script de Impacket
), o bien, mediante el mismo Evil-WinRM
:
evil-winrm -i 10.10.10.161 -u 'Administrator' -H 'HASH'
impacket-psexec administrator@10.10.10.161 -hash HASH