Collect Microsoft Active Directory domain controller logs

Active Directory (AD) is a directory service developed by Microsoft for Windows network domains. An AD domain controller responds to security authentication requests within a Windows domain. Most Active Directory logging, especially for security-related activity, is done via the Windows Event Log.

Active Directory logs are essential for many reasons. They provide insights into user and group activities, including changes to permissions, account lockouts, failed logins, and other security-related events. AD logs can help in detecting suspicious activity or security breaches, troubleshooting issues, and monitoring the health and performance of your Active Directory environment. Additionally, you can use your domain controller logs to meet regulatory compliance requirements and auditing policies.

There are two crucial logs to monitor on a domain controller:

Active Directory security logs

These logs contain information about authentication and authorization attempts, such as successful and failed logins, changes to security policies, and account lockouts.

Directory Service logs

These logs provide information about Active Directory operations, such as changes to user accounts, group memberships, and permissions.

Ultimately, both fall into the "critical logs" category from an IT security perspective.

Collect Active Directory security logs

The domain controller generates events for suspicious activities, including attempts to change Active Directory modes or attempted replay attacks. You can monitor these security logs via Windows Event Log by filtering for event source ActiveDirectory_DomainService.

The event IDs to monitor always depends on your use case. There is no silver bullet here. Nevertheless, below is a list of essential event IDs we consider a must-collect in any scenario.

Table 1. A must-collect list of Active Directory DC Windows event IDs
Event ID Description

4618

A monitored security event pattern has occurred.

4649

A replay attack was detected. May be a harmless false positive due to a misconfiguration error.

4719

System audit policy was changed.

4765

SID History was added to an account.

4766

An attempt to add SID History to an account failed.

4794

An attempt was made to set the Directory Services Restore Mode.

4897

Role separation was enabled.

4964

Special groups have been assigned to a new logon.

5124

A security setting was updated on OCSP Responder Service.

1102

The audit log was cleared.

For a complete list of Active Directory events, see Events to Monitor on Microsoft Learn.

Example 1. Collecting Active Directory security logs

This example uses the im_msvistalog input module to capture critical security logs on a Windows Server 2022 AD domain controller.

Windows Event Log only supports a limited number of event IDs per query. Due to this limitation, the configuration uses an Exec block to collect the required event IDs instead of listing every event ID in the query.

nxlog.conf
<Extension json>
    Module             xm_json
    PrettyPrint        TRUE
</Extension>

define SecurityIDs     4618, 4649, 4719, 4765, 4766, 4794, 4897, 4964, 5124, \
                       4621, 4675, 4692, 4693, 4706, 4713, 4714, 4715, 4716, \
                       4724, 4727, 4735, 4737, 4739, 4754, 4755, 4764, 4780, \
                       4816, 4865, 4866, 4867, 4868, 4870, 4882, 4885, 4890, \
                       4892, 4896, 4906, 4907, 4908, 4912, 4960, 4961, 4962, \
                       4963, 4965, 4976, 4977, 4978, 4983, 4984, 5027, 5028, \
                       5029, 5030, 5035, 5037, 5038, 5120, 5121, 5122, 5123, \
                       5376, 5377, 5453, 5480, 5483, 5484, 5485, 6145, 6273, \
                       6274, 6275, 6276, 6277, 6278, 6279, 6280, 4608, 4609, \
                       4610, 4611, 4612, 4614, 4615, 4616, 4624, 4625, 4634, \
                       4647, 4648, 4656, 4657, 4658, 4660, 4661, 4662, 4663, \
                       4672, 4673, 4674, 4688, 4689, 4690, 4691, 4696, 4697, \
                       4698, 4699, 4700, 4701, 4702, 4704, 4705, 4707, 4717, \
                       4718, 4720, 4722, 4723, 4725, 4726, 4728, 4729, 4730, \
                       4731, 4732, 4733, 4734, 4738, 4740, 4741, 4742, 4743, \
                       4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, \
                       4753, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4767, \
                       4768, 4769, 4770, 4771, 4772, 4774, 4775, 4776, 4778, \
                       4779, 4781, 4783, 4785, 4786, 4787, 4788, 4789, 4790, \
                       4869, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, \
                       4879, 4880, 4881, 4883, 4884, 4886, 4887, 4888, 4889, \
                       4891, 4893, 4894, 4895, 4898, 5136, 5137

define BitLockerIDs    24586, 24592, 24593, 24594

define EventlogID      1102

define SecuritySrc     Microsoft-Windows-Security-Auditing
define BitLockerSrc    Microsoft-Windows-BitLocker-Driver
define EventlogSrc     Microsoft-Windows-Eventlog

<Input events> 
    Module    im_msvistalog
    <QueryXML>
        <QueryList>
            <Query Id="0">
                <Select Path="Security">*[System[Provider[
                    @Name='%EventlogSrc%' or
                    @Name='%SecuritySrc%']]]
                </Select>
                <Select Path="System">*[System[Provider[
                    @Name='%BitLockerSrc%']]]
               </Select>
            </Query>
         </QueryList>
    </QueryXML>
    <Exec>
        if not (defined($SourceName) and
           (($EventID IN (%SecurityIDs%) and $SourceName == "%SecuritySrc%") or
           ($EventID IN (%BitLockerIDs%) and $SourceName == "%BitLockerSrc%") or
           ($EventID == %EventlogID% and $SourceName == "%EventlogSrc%")))
           drop();
        to_json();       
    </Exec>
</Input>
Output sample in JSON (EventID 1102, "The audit log was cleared")
{
  "EventTime": "2023-04-04T09:28:57.792328+02:00",
  "Hostname": "DC001.nxlogtest.com",
  "Keywords": "4620693217682128896",
  "LevelValue": 4,
  "EventType": "INFO",
  "SeverityValue": 2,
  "Severity": "INFO",
  "EventID": 1102,
  "SourceName": "Microsoft-Windows-Eventlog",
  "ProviderGuid": "{FC65DDD8-D6EF-4962-83D5-6E5CFE9CE148}",
  "Version": 0,
  "TaskValue": 104,
  "OpcodeValue": 0,
  "RecordNumber": 36405,
  "ExecutionProcessID": 380,
  "ExecutionThreadID": 3088,
  "Channel": "Security",
  "Message": "The audit log was cleared.\r\nSubject:\r\n\tSecurity ID:\tS-1-5-21-3589175892-3624815508-1412135724-500\r\n\tAccount Name:\tAdministrator\r\n\tDomain Name:\tNXLOGTEST\r\n\tLogon ID:\t0x800A8",
  "Category": "Log clear",
  "Opcode": "Info",
  "Level": "Information",
  "LogFileCleared.SubjectUserSid": "S-1-5-21-3589175892-3624815508-1412135724-500",
  "LogFileCleared.SubjectUserName": "Administrator",
  "LogFileCleared.SubjectDomainName": "NXLOGTEST",
  "LogFileCleared.SubjectLogonId": "0x800a8",
  "EventReceivedTime": "2023-04-04T09:28:58.795764+02:00",
  "SourceModuleName": "events",
  "SourceModuleType": "im_msvistalog"
}

Advanced security audit policy on an AD domain controller

The goal of security auditing is to track who did what and when. Unfortunately, auditing all users' activities generates tremendous amounts of logging and can quickly become overwhelming. However, Windows security auditing supports advanced audit policies, allowing you to implement fine-grained auditing.

You can enable AD audit logs via the Group Policy Advanced Audit Policy. This policy comprises several activity-specific subcategories, including Directory Service access. Follow these steps to enable the Advanced Audit Policy and configure DS auditing:

  1. Log in to the server as a domain administrator.

  2. Load the Group Policy Management Editor from Server Manager > Tools.

  3. Expand the Domain Controllers organizational unit (OU), right-click on Default Domain Controllers Policy, and click Edit…​.

    Group Policy Management
  4. Expand Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies > DS Access.

    Group Policy Management
  5. Enable all the policies in this category to start auditing Directory Service access.

Refer to Step-By-Step: Enabling Advanced Security Audit Policy via DS Access on Microsoft Learn for more information on the Advanced Audit Policy and descriptions of event IDs.

Example 2. Collecting Active Directory audit logs

Once you enable security auditing, you can collect the relevant events with the NXLog Agent im_msvistalog input module. For example, this configuration collects all Windows security audit events of critical, warning, or error level.

nxlog.conf
<Extension json>
    Module         xm_json
    PrettyPrint    TRUE
</Extension>

<Input SecurityAuditEvents>
    Module         im_msvistalog
    <QueryXML>
        <QueryList>
            <Query Id="0" Path="Security">
                <Select Path="Security">*[System[Provider[@Name='Microsoft-Windows
                -Security-Auditing'] and (Level=1 or Level=2 or Level=3) and 
                ((EventID=4928 and EventID=4931) or (EventID=4932 and EventID=4937)
                or EventID=4662 or (EventID=5136 and EventID = 5141))]]</Select>
            </Query>
        </QueryList>
    </QueryXML>
        <Exec>
        $EventData = extract_xml("/Event/EventData", $EventXML);
        if $EventData == ""
        {
            delete($EventData);
        }

        $UserData = extract_xml("/Event/UserData", $EventXML);
        if $UserData == ""
        {
            delete($UserData);
        }

        delete($EventXML); 
        to_json(); 
    </Exec>
</Input>
Output sample in JSON (EventID 5136, "A directory service object was modified")
{
  "EventTime": "2023-04-03T12:28:30.349741+02:00",
  "Hostname": "DC001.nxlogtest.com",
  "Keywords": "9232379236109516800",
  "LevelValue": 0,
  "EventType": "AUDIT_SUCCESS",
  "SeverityValue": 2,
  "Severity": "INFO",
  "EventID": 5136,
  "SourceName": "Microsoft-Windows-Security-Auditing",
  "ProviderGuid": "{54849625-5478-4994-A5BA-3E3B0328C30D}",
  "Version": 0,
  "TaskValue": 14081,
  "OpcodeValue": 0,
  "RecordNumber": 36383,
  "ExecutionProcessID": 672,
  "ExecutionThreadID": 776,
  "Channel": "Security",
  "Message": "A directory service object was modified.\r\n\t\r\nSubject:\r\n\tSecurity ID:\t\tS-1-5-21-3589175892-3624815508-1412135724-500\r\n\tAccount Name:\t\tAdministrator\r\n\tAccount Domain:\t\tNXLOGTEST\r\n\tLogon ID:\t\t0x84C17\r\n\r\nDirectory Service:\r\n\tName:\tnxlogtest.com\r\n\tType:\tActive Directory Domain Services\r\n\t\r\nObject:\r\n\tDN:\tCN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=POLICIES,CN=SYSTEM,DC=NXLOGTEST,DC=COM\r\n\tGUID:\t{88db9c05-2adb-4fe6-8dfe-26897bc823c7}\r\n\tClass:\tgroupPolicyContainer\r\n\t\r\nAttribute:\r\n\tLDAP Display Name:\tversionNumber\r\n\tSyntax (OID):\t2.5.5.9\r\n\tValue:\t7\r\n\t\r\nOperation:\r\n\tType:\tValue Added\r\n\tCorrelation ID:\t{f696f890-7c5b-41f0-bc82-aaaf73a80646}\r\n\tApplication Correlation ID:\t-",
  "Category": "Directory Service Changes",
  "Opcode": "Info",
  "Level": "Information",
  "OpCorrelationID": "{f696f890-7c5b-41f0-bc82-aaaf73a80646}",
  "AppCorrelationID": "-",
  "SubjectUserSid": "S-1-5-21-3589175892-3624815508-1412135724-500",
  "SubjectUserName": "Administrator",
  "SubjectDomainName": "NXLOGTEST",
  "SubjectLogonId": "0x84c17",
  "DSName": "nxlogtest.com",
  "DSType": "%%14676",
  "ObjectDN": "CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=POLICIES,CN=SYSTEM,DC=NXLOGTEST,DC=COM",
  "ObjectGUID": "{88db9c05-2adb-4fe6-8dfe-26897bc823c7}",
  "ObjectClass": "groupPolicyContainer",
  "AttributeLDAPDisplayName": "versionNumber",
  "AttributeSyntaxOID": "2.5.5.9",
  "AttributeValue": "7",
  "OperationType": "%%14674",
  "EventReceivedTime": "2023-04-03T12:52:38.154964+02:00",
  "SourceModuleName": "events",
  "SourceModuleType": "im_msvistalog",
  "EventData": "<EventData><Data Name=\"OpCorrelationID\">{f696f890-7c5b-41f0-bc82-aaaf73a80646}</Data><Data Name=\"AppCorrelationID\">-</Data><Data Name=\"SubjectUserSid\">S-1-5-21-3589175892-3624815508-1412135724-500</Data><Data Name=\"SubjectUserName\">Administrator</Data><Data Name=\"SubjectDomainName\">NXLOGTEST</Data><Data Name=\"SubjectLogonId\">0x84c17</Data><Data Name=\"DSName\">nxlogtest.com</Data><Data Name=\"DSType\">%%14676</Data><Data Name=\"ObjectDN\">CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=POLICIES,CN=SYSTEM,DC=NXLOGTEST,DC=COM</Data><Data Name=\"ObjectGUID\">{88db9c05-2adb-4fe6-8dfe-26897bc823c7}</Data><Data Name=\"ObjectClass\">groupPolicyContainer</Data><Data Name=\"AttributeLDAPDisplayName\">versionNumber</Data><Data Name=\"AttributeSyntaxOID\">2.5.5.9</Data><Data Name=\"AttributeValue\">7</Data><Data Name=\"OperationType\">%%14674</Data></EventData>"
}

Troubleshooting Active Directory domain controller promotion (DCPROMO) issues

Microsoft provides a comprehensive guide on Troubleshooting Domain Controller Deployment. One of the most important log sources you will come across in the guide is the C:\Windows\debug\dcpromo.log file, where the DCPROMO tool logs the entire DC promotion and demotion process. Each consecutive run of DCPROMO creates an additional log file in the format C:\Windows\debug\dcpromo.001.log, etc.

Example 3. Collecting DCPROMO logs

This configuration uses the im_file input module to read all DCPROMO log files. It then parses each log record into structured data using a regular expression. Furthermore, it uses the parsedate() function to parse the event timestamp to datetime.

Log sample
04/03/2023 04:43:47 [INFO] Creating directory partition: CN=Configuration,DC=nxlog,DC=org; 1270 objects remaining
04/03/2023 04:43:47 [INFO] Creating directory partition: CN=Configuration,DC=nxlog,DC=org; 1269 objects remaining
04/03/2023 04:43:47 [INFO] Creating directory partition: CN=Configuration,DC=nxlog,DC=org; 1268 objects remaining
nxlog.conf
<Extension json>
    Module         xm_json
    PrettyPrint    TRUE
</Extension>

<Input dcpromo>
    Module         im_file
    File           'C:\Windows\debug\DCPROMO.log'
    File           'C:\Windows\debug\DCPROMO.*.log'
    <Exec>
        if $raw_event =~ /^(\d\d)\W(\d\d)\W(\d{4}) (\d\d:\d\d:\d\d) \[(\S+)\] (.+)$/
        {    
            $EventTime = parsedate($3 + '-' + $1 + '-' + $2 + ' ' + $4);
            $Severity = $5;
            $Message = $6;
        }
        to_json();
    </Exec>
</Input>
Output sample in JSON
{
    "EventReceivedTime": "2023-04-03T04:43:48.841091+02:00",
    "SourceModuleName": "dcpromo",
    "SourceModuleType": "im_file",
    "EventTime": "2023-04-03T04:43:47.000000+02:00",
    "Severity": "INFO",
    "Message": "Creating directory partition: CN=Configuration,DC=nxlog,DC=org; 1270 objects remaining"
}
Disclaimer

While we endeavor to keep the information in our guides up to date and correct, NXLog makes no representations or warranties of any kind, express or implied about the completeness, accuracy, reliability, suitability, or availability of the content represented here. We update our screenshots and instructions on a best-effort basis.

The accurateness of the content was tested and proved to be working in our lab environment at the time of the last revision with the following software versions:

Windows Server 2022 Standard
NXLog Agent version 5.7.7898

Last revision: 4 April 2023