Machine Information
| Field | Details |
|---|---|
| Name | Certified |
| Platform | HackTheBox |
| OS | Windows |
| Difficulty | Medium |
You start this box with valid low-privilege domain credentials: judith.mader / judith09. The path to Administrator is a chain of ACL abuses through Active Directory — no CVE, no exotic exploit, just misplaced permissions and the right tooling.
TL;DR
judith.mader has WriteOwner on the Management group. That lets us take ownership, grant ourselves FullControl via DACL edit, and add judith to the group. Management has GenericWrite on management_svc, so we use pywhisker to inject shadow credentials and retrieve the NTLM hash via PKINITtools. With management_svc on the box we find GenericAll on ca_operator in BloodHound, reset its password, then exploit ESC9 with certipy to forge an Administrator certificate. Final step: psexec as SYSTEM.
Recon
Standard nmap first to see what we’re dealing with:

Typical Windows DC setup — 445, 389, 636, 3268, 5985, and the Kerberos ports. Nothing unusual on the surface.
Enumeration
With valid creds we can enumerate the domain right away with nxc:

The domain is certified.htb. We can see users like management_svc, ca_operator, alexander.huges, and gregory.cameron alongside the usual built-in accounts. Let’s fire up BloodHound to map the relationships.
| |

BloodHound immediately lights up something interesting. Judith has WriteOwner on the Management group:

And if we follow the path further, Management has GenericWrite on management_svc:

One more hop to check — management_svc has GenericAll on ca_operator:

That’s our full attack chain right there. Three hops and we’ll have enough to escalate to admin via certificate abuse.
One thing worth noting: when I first tried GetUserSPNs to check for Kerberoastable accounts, I got a clock skew error:

Kerberos requires clocks to be within 5 minutes of the DC. Quick fix:
| |

Foothold — ACL Chain: WriteOwner → Management → management_svc
Step 1: Take ownership of the Management group
WriteOwner means we can set the owner of the object to ourselves. Once we own it, we can modify the DACL and grant FullControl:
| |

Now add judith to Management:
| |
Verify she’s in:
| |
Step 2: Abuse GenericWrite on management_svc via Shadow Credentials
GenericWrite on a user means we can write to their msDS-KeyCredentialLink attribute — that’s what enables Shadow Credentials. The idea is to inject our own certificate-based credential, then use it to get a TGT and extract the NTLM hash without ever touching the user’s password.
| |

This gives us a certificate and key pair. Now use PKINITtools to authenticate with it and get a TGT:
| |

With a TGT in hand, we can use getnthash.py to recover the NTLM hash:
| |

NTLM hash: a091c1832bcdd4677c28b5a6a1295584
Quick check that WinRM is open for this account:

| |

User flag
| |

Privilege Escalation — GenericAll on ca_operator → ESC9
Back in BloodHound, management_svc has GenericAll over ca_operator. GenericAll is full object control — we can reset the password without knowing the current one.
| |

Verify the creds work:

Now let’s see what ca_operator can do with the CA. Use certipy to find vulnerable templates:
| |
ESC9 — the CertifiedAuthentication template has no security extension (szOID_NTDS_CA_SECURITY_EXT). This means we can request a certificate for one UPN and then change it back — the CA won’t bind the cert to the original requester’s identity. We can impersonate Administrator.
The exploit steps:
1. Update ca_operator’s UPN to match Administrator, using management_svc’s hash (GenericAll means we can write attributes):
| |
2. Request the certificate as ca_operator (whose UPN is now administrator@certified.htb):
| |
3. Revert the UPN back to avoid breaking things:
| |
4. Authenticate with the forged cert to get the Administrator NTLM hash:
| |

Administrator hash: 0d5b49608bbce1751f708748f67e2d34
Root
| |

Takeaways
- ESC9 doesn’t need template modification rights - just a user with enrollment rights and another with GenericAll or GenericWrite on them. The attack works because the cert’s SAN is set from the UPN at request time, and the CA doesn’t cryptographically bind it to the requester.
- WriteOwner is often overlooked — it doesn’t look as scary as GenericAll, but it’s a path to anything. Own the object, edit the DACL, you have whatever you want.
- Shadow Credentials are stealthy — you’re not touching the user’s password or SPNs. You’re writing to
msDS-KeyCredentialLinkwhich doesn’t trigger password-change alerts. Hard to detect without dedicated AD CS monitoring. - BloodHound with LEGACY mode picked up all these edges cleanly. Always worth running collection with
-c all.
