DCSync Detection

13 April 2022

Background

Learning the detection techniques are always part of my study. As a red teamer, It is equally important to know how to detect attacks in order to provide recommendations and possibly find a way to bypass it. In this blog post, I would like document my study on DCSync detection.

Introduction to DCSync

DCSync is a well-known technique allowing an attacker to extract password hash from the domain controller by simulating the behaviour of domain replication. Especially, gaining access to the KRBTGT password hash allows the attacker to forge a Golden Ticket to maintain access and stay stealthy in an enterprise environment.

DCSync leverages Directory Replication Service Remote Protocol (MS-DRSR), which is an RPC protocol for replication and management of data in Active Directory. The Microsoft API which implements such protocol is called DRSUAPI.

Usually, only domain controllers, domain administrators, and enterprise administrators have the privileges required to perform DCSync.

However, it is not uncommon to see service accounts are granted with "Full Control" / "GenericAll" privilege on the domain root which leads to abuse of DCSync.

Below are the key permissions that could perform DCSync attack:

  • Replicating Directory Changes

  • Replicating Directory Changes All

  • Replicating Directory Changes In Filtered Set

  • Full Control

Ways to Validate the DCSync Privilege

Before I start the discussion on the detection techniques, it is important to know how to check the current environment setup and validate which users were granted privileges that could perform DCSync.

Checking in GUI (in Domain Controller):

Open "Active Directory Users and Computers" -> Right click the domain object -> Select "Properties" -> "Security":

Checking in Command Line (Any Domain Joined System with ActiveDirectory PowerShell Module):

Import-Module ActiveDirectory
(Get-Acl "ad:\dc=lab,dc=internal").Access | ? {$_.IdentityReference -and ($_.ObjectType -eq "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2" -or $_.ObjectType -eq "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2" -or $_.ObjectType -eq "89e95b76-444d-4c62-991a-0facbeda640c" -or $_.ActiveDirectoryRights -match "WriteDacl" -or $_.ActiveDirectoryRights -Contains "GenericAll") }

Other than those 4 permissions mentioned above, it is easy to be overlooked by people that accounts with WriteDacl permission on domain root could be abused to grant DCSync permissions to other accounts. "Exchange Windows Permissions" is a classic example that is a group granted with WriteDacl to the domain root by default. It allows anyone who controls the Exchange servers to assign DCSync privilege and achieve domain dominance.

DCSync Detection Techniques

For easier understanding, I divided the discussion into two main parts, one is host-based and the other is network-based detection. Particularly, the techniques below would be covered in the following sections:

  • Host-Based Detection

    1. Event Tracing for Windows (Microsoft-Windows-RPC)

    2. 4662 Event Log Detection

  • Network-Based Detection (DRSUAPI)

Host-Based Detection

1. Event Tracing for Windows (Microsoft-Windows-RPC)

Since DCSync uses RPC protocol, Microsoft-Windows-RPC ETW telemetry provides a good source to monitor the attack at the endpoint level.

All RPC services have its own corresponding UUID. Therefore, I started to search on the Microsoft doc and obtain the UUID for DRSUAPI. Filtering the UUID in the ETW RPC events could eliminate RPC events that are not relevant to domain replication:

With reference to krabsetw, I created a simple ETW agent for Microsoft-Windows-RPC and filter the UUID of the DRSUAPI in order to test the detection:

using System;
using Microsoft.O365.Security.ETW;

namespace SimpleETWAgent
{
    class Program
    {
        static void Main(string[] args)
        {
            var filter = new EventFilter(
                Filter.EventIdIs(5)
                );

            filter.OnEvent += (IEventRecord r) =>
            {
                var opNum = r.GetUInt32("ProcNum");
                var networkaddress = r.GetUnicodeString("NetworkAddress");
                var options = r.GetUnicodeString("Options");
                Guid interfaceuuid = new Guid(r.GetBinary("InterfaceUuid"));
                // Uuid for DRSUAPI
                if (interfaceuuid.ToString() == "e3514235-4b06-11d1-ab04-00c04fc2dcd2")
                {
                    Console.WriteLine($"{r.TaskName} Event: {r.Id}");
                    Console.WriteLine($"InterfaceUuid: {interfaceuuid}");
                    Console.WriteLine($"Process ID: {r.ProcessId}");
                    Console.WriteLine($"NetworkAddress: {networkaddress}");
                    Console.WriteLine($"OpNum: {opNum}");
                    Console.WriteLine($"Options: {options}");
                    Console.WriteLine($"Timestamp: {r.Timestamp.ToLocalTime()}");
                    Console.WriteLine("=====================================");
                }
            };

            var provider = new Provider("Microsoft-Windows-RPC");
            provider.AddFilter(filter);

            var trace = new UserTrace();
            trace.Enable(provider);

            Console.CancelKeyPress += (sender, eventArg) =>
            {
                if (trace != null)
                {
                    Console.WriteLine("==========Stopping the ETW===========");
                    trace.Stop();
                }
            };

            Console.WriteLine("===========Started the ETW===========");
            trace.Start();
        }
    }
}

Let's execute the DCSync using Mimikatz and monitor the events using our newly created ETW agent:

We could instantly see a couple of events that have been generated targeting the domain controller (dc01.lab.internal). Among the events, we can see a lot of different OpNums. a quick mapping with the Microsoft doc shows the functionality of each OpNum as below:

  • OpNum 0: IDL_DRSBind

    • The IDL_DRSBind method creates a context handle that is necessary to call any other method in this interface.

  • OpNum 16: IDL_DRSDomainControllerInfo

    • The IDL_DRSDomainControllerInfo method retrieves information about DCs in a given domain.

  • OpNum 12: IDL_DRSCrackNames

    • The IDL_DRSCrackNames method looks up each of a set of objects in the directory and returns it to the caller in the requested format.

  • OpNum 3: IDL_DRSGetNCChanges

    • The IDL_DRSGetNCChanges method replicates updates from an NC replica on the server.

  • OpNum 1: IDL_DRSUnbind

    • The IDL_DRSUnbind method destroys a context handle previously created by the IDL_DRSBind method.

Particularly, OpNum3 - "IDL_DRSGetNCChanges" is what we are looking for regarding the domain replication service.

Since domain replication activity from non-domain controller systems is generally uncommon, monitoring RPC ETW on generic user workstations/servers could be a way to detect potential DCSync attacks. This kind of monitoring could be relied on a separate ETW agent or the Endpoint Detection and Response (EDR) product.

A updated RPC ETW agent filtering the DSRUAPI UUID and OpNum 3 would serve as a simple solution to detect DCSync at endpoint level.

2. Windows Security Log Event ID 4662

Monitoring Windows Security event log in the domain controller is relatively well-known detection technique and probably an easier way to detect a potential DCSync attack.

For every domain replication activity, a Windows 4662 event log (An operation was performed on an object) will be generated. To narrow down the event to contain replication changes only, the following control access rights could be used for filtering:

  • DS-Replication-Get-Changes (1131f6aa-9c07-11d1-f79f-00c04fc2dcd2)

  • DS-Replication-Get-Changes-All (1131f6ad-9c07-11d1-f79f-00c04fc2dcd2)

  • DS-Replication-Get-Changes-In-Filtered-Set (89e95b76-444d-4c62-991a-0facbeda640c)

  • Below demonstrated a 4662 event generated by the domain controller:

For the DCSync attack, the "Account Name" in the 4662 events will be typically changed to a user name or a non-domain controller computer name. A sample DCSync event would be similar to the below:

By comparing the above legitimate domain replication and DCSync events, "Account Name" is the key field to identify a potential DCSync attack attempts. The "Account Name" became a username instead of a domain controller.

It is worth noting that some legitimate service such as AD Connect MSOL_ user will perform replication process too. Therefore, it is important to understand the environment and exclude those accounts if necessary.

The detection logic will focus on filtering the GUID of domain replication and locating "Account Name" which is not a domain controller computer account.

Sample Splunk SIEM query to detect DCSync:

index=main EventCode=4662 Access_Mask=0x100 AND ("Replicating Directory Changes all" OR "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2" OR "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2" OR "89e95b76-444d-4c62-991a-0facbeda640c") AND Account_Name!="DC01$"

While I am testing the 4662 detection, I noted that all domain replication performed by computer accounts will not generate any 4662 events. It frustrated me for a while and I thought there might be some problems in my setup. However, I found a post "A primer on DCSync attack and detection" that the author clearly mentioned it is required to add "Domain Computers SACL" on the Domain Object auditing item in order to detect DCSync that is performed by computer account.

Steps to add "Domain Computers" for auditing:

  1. Open "Active Directory Users and Computers"

  2. Right click your domain and select "Properties"

  3. Select "Advanced" On "Security" tab

  4. Select "Auditing" and "Add"

  5. Select "Select a principal" and add "Domain Computers"

  6. Scroll down to the bottom and click "Clear All"

  7. Tick "Replicating Directory Changes", "Replicating Directory Changes All", and "Replicating Directory Changes in Filtered Set" and save your changes

Side note: Stealthbits did an excellent research regarding a domain persistence technique by granting a user with "DS-Install-Replica" privilege. It provides sufficient privilege for the user to convert a domain computer (primary ID 515) to domain controller (primary ID 516) by manipulating the UserAccountControl to UF_SERVER_TRUST_ACCOUNT.

In the detection perspective, since the account who performed DCSync attack is no longer a domain computer but a domain controller, enabling auditing on "Domain Computers" in the domain object would not be sufficient.

In this scenario, you might need to include "Domain Controllers" in your domain object too.

Network-Based Detection

Since DRSUAPI is a protocol mainly for domain replication, it is rare to see this protocol among non-DC subnets. This nature provides a good chance for the blue team to develop a network detection rule to identify DRSUAPI traffic for DsGetNCChanges from non-DC subnet to DCs.

Summary

Adopting any of the above detection techniques could increase the chance of detecting an adversary attack.

However, it is worth noting that the above detection is not 100% bulletproof to identify all DCSync attacks. A poorly designed detection rule might leave attackers the opportunity to bypass the detection.

For example, I have seen some of the detection rules for 4662 events trigger alerts only when the "Account Name" is not a computer account (ending with $). It might leave room for attackers to bypass the detection by creating a new computer account and granting it the privilege for DCSync attack. As a result, It is always suggested to filter only known and exact "Account Name" instead of wildcard filtering.

Also, performing DCSync on the domain controller will most likely bypass most of the detection techniques since the attack traffic is blended into the normal domain replication traffic. Therefore, it is important for the blue team to fully understand the attack and combine other security detections such as abnormal login attempts on DC to minimize the "vulnerability" for detection evasion.

Reference

Last updated