DCSync: replicating secrets out of Active Directory, and catching it

  • windows
  • active-directory
  • dcsync
  • detection
  • hardening

Proof of concept on GitHub

DCSync is the step a great many Active Directory compromises converge on. Once an attacker controls any principal that holds directory-replication rights, they can ask a domain controller to hand over account secrets using the same protocol DCs use to replicate to each other. No code runs on the DC, nothing is dropped to its disk, and the krbtgt hash that comes back lets the attacker forge Kerberos tickets at will. It is catalogued as MITRE ATT&CK T1003.006. This post explains the mechanism, the rights it depends on, and spends most of its length on detection and prevention, because this is one of the most detectable high-impact techniques in AD when you are logging the right event.

For how an attacker reaches the replication grant in the first place without a privileged password, see coerced NTLM relay to LDAP; this post is about the replication step itself.

The mechanism

Domain controllers keep themselves in sync with the Directory Replication Service Remote Protocol (MS-DRSR). When one DC needs an object's current state, it calls DRSGetNCChanges on another DC, which returns the object including its secret attributes (password hashes, Kerberos keys). DCSync is simply a non-DC making that same DRSGetNCChanges request and being answered as though it were a replication partner.

The server does not care that the caller is a workstation or a user account. It cares only that the caller holds the replication extended rights on the domain object. That is the entire trust decision, and it is why DCSync needs no code execution on the DC: it is a legitimate protocol call made by an illegitimate caller.

DCSync: a replication request from a non-DC A controlled account that holds the replication rights asks the domain controller to replicate an account with the same protocol domain controllers use among themselves. The DC returns the secret attributes. No code runs on the DC. Controlled account holds replication rights Domain Controller answers as to a DC peer 1 DRSGetNCChanges: replicate this account needs DS-Replication-Get-Changes-All 2 secret attributes: NT hashes, krbtgt keys no code runs on the DC; it checks the rights, not who you are
DCSync is a non-DC making the same replication request a DC would. The server returns password hashes because the caller holds the replication rights, not because it is a domain controller, which is why one 4662 rule for a non-DC replication request catches it.

DCSync also appears as the domain-wide store in Windows credential access, and one way a foothold reaches the replication rights it needs is coerced NTLM relay to DCSync.

The rights it depends on

Three control-access rights on the domain head govern replication, identified by GUID:

  • DS-Replication-Get-Changes, GUID 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2
  • DS-Replication-Get-Changes-All, GUID 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2
  • DS-Replication-Get-Changes-In-Filtered-Set, GUID 89e95b76-444d-4c62-991a-0facbeda640c

Holding Get-Changes together with Get-Changes-All is enough to replicate secret attributes for any account. Legitimately, these rights belong to domain controllers, to the Enterprise Domain Controllers group, and to a small number of directory-sync services. Any user or non-DC computer that holds them is a finding on its own, whether or not it has been abused yet. BloodHound surfaces these edges directly, which is how both attackers and defenders enumerate them.

How it is performed

The technique is implemented in standard public tooling. Mimikatz exposes it as lsadump::dcsync, and Impacket's secretsdump.py performs it remotely with -just-dc (or -just-dc-user <account> for a single target). Given a controlled account that holds the replication rights, an operator requests krbtgt and Administrator first: krbtgt enables golden-ticket forgery, and the Administrator hash enables pass-the-hash to Domain Admin. The output is NTLM hashes (and Kerberos keys), not cleartext, which is all that is needed for pass-the-hash and ticket forging.

That is the whole offense: acquire the rights (by whatever path), then make the replication request. The interesting engineering, for both sides, is on detection and prevention.

Tooling and usage

The canonical implementations are public, so for real use you point at them; the C skeleton in the linked repo is only for learning the protocol. All require a principal that already holds the replication rights. Placeholders below.

# Impacket, remote, no code on the DC (the common case)
secretsdump.py -just-dc 'domain.local/<controlled-account>:pass@<dc>'                 # everything
secretsdump.py -just-dc-user krbtgt 'domain.local/<controlled-account>:pass@<dc>'     # one account
secretsdump.py -just-dc -hashes :<nt-hash> 'domain.local/<controlled-account>@<dc>'   # pass-the-hash

# Mimikatz, run on a host (the original C implementation)
lsadump::dcsync /domain:domain.local /user:krbtgt

# NetExec, which wraps the same drsuapi path
nxc smb <dc> -u <controlled-account> -p 'pass' --ntds

Pull krbtgt (golden-ticket capable) and Administrator first. These are the tools to use in practice; the skeleton exists to show what they do on the wire, not to replace them.

Detection

DCSync is loud if, and only if, you have the auditing configured. The signal is strong because a legitimate DCSync by a non-DC essentially never happens.

  • Event 4662, the primary signal. On domain controllers, Security event 4662 (an operation was performed on a directory-service object) with an access mask including Control Access (0x100) and a Properties field referencing the replication GUIDs above is the core detector. The alert logic is simple: fire when the requesting principal is not a domain controller machine account. Legitimate replication comes from DC computer accounts; a user or a non-DC computer requesting Get-Changes-All is the attack.
  • Enable the auditing first. 4662 for these GUIDs is not logged by default. You need Advanced Audit Policy for Directory Service Access enabled on DCs, and a SACL on the domain object that audits the replication rights. Without both, the event never fires. Validate end to end in a lab before trusting the absence of alerts.
  • Tune out the real replication tools. Exclude DC machine accounts, and known sync services such as Azure AD Connect (the MSOL_ account) and management systems like SCCM, which legitimately touch replication. A common Sigma approach filters machine accounts ending in $ that are not DCs and whitelists the known sync identities, which keeps the false-positive rate low.
  • Correlate for attribution. Join 4662 with the logon event (4624) by Logon ID on the DC to tie the replication request to a source host and session, which turns "something DCSynced" into "this host, this account, at this time."
  • Network corroboration. DCSync rides MS-DRSR over RPC, so DRSGetNCChanges calls observed from a non-DC source address are an independent, host-log-free indicator for network monitoring.

The highest-confidence detector is the simplest to state: a replication request for directory secrets from anything that is not a domain controller. Alert on it on its own; it catches DCSync regardless of how the rights were obtained.

Prevention and response

  • Audit and restrict who holds the rights. Enumerate every principal with DS-Replication-Get-Changes and -Get-Changes-All on the domain object (BloodHound, or a direct ACL review) and remove them from anything that is not a DC or a documented sync service. Removing the grant removes the technique; a user or member server should never hold it.
  • Protect the path to the grant. Most DCSync abuse starts by first obtaining those rights, often via an NTLM relay to LDAP or an ACL-abuse chain. Enforce LDAP signing and channel binding, restrict NTLM, and watch for the ACL write (event 5136) that adds a replication right to an account, which is the escalation step and should essentially never happen outside controlled administration.
  • Tiered administration. Keep DA-equivalent credentials off member servers and workstations so a foothold has less to harvest on the way to the rights.
  • Response after a confirmed DCSync. Treat the whole domain as compromised: disable the implicated account, investigate for lateral movement using the 4662/4624 correlation, and rotate krbtgt twice in a controlled sequence (two resets with replication between them) because any captured krbtgt key allows golden-ticket forgery until it is rotated. Rotate other exposed privileged credentials as well.

Proof of concept

The linked repository carries a deliberately incomplete teaching skeleton in C: it builds the authenticated RPC binding to a DC's drsuapi interface and lays out the IDL_DRSGetNCChanges single-object replication request, with the two hardest parts (generating the RPC stubs from the public MS-DRSR IDL, and decrypting the returned secret attributes with the session key) left as marked exercises. It is there to make the mechanism legible, not to hand over a turnkey dumper; the canonical complete implementations are already public in Impacket and Mimikatz. The folder also ships the Sigma rule from the detection section.

Use

This is written for authorized assessment and, more to the point here, for the defenders who have to catch it. DCSync is unusually detectable for its impact: one well-configured 4662 rule reliably catches it. The two things worth doing before you ever need the alert are to turn that auditing on and to make sure no account outside your DCs and sync services holds the replication rights in the first place.

References

Proof of concept on GitHub

Back to all techniques