Query Details

Security Event Non DC Active Directory Replication

Query

let query_frequency = 15m;
let query_period = 3h;
let query_wait = 30m;
let replication_threshold = 10;
let _BenignDSReplication =
    _GetWatchlist("Activity-ExpectedSignificantActivity")
    | where Activity == "DSReplication"
    | project Account = ActorPrincipalName, IpAddress = SourceAddress
;
SecurityEvent
| where ingestion_time() between (ago(query_frequency + query_wait) .. ago(query_wait))
| where EventID == 4662 and ObjectServer == "DS" and AccountType != "Machine"
| where Properties has_any (
    // https://learn.microsoft.com/en-us/windows/win32/adschema/extended-rights
    "{1131f6ad-9c07-11d1-f79f-00c04fc2dcd2}", //DS-Replication-Get-Changes-All
    "{1131f6aa-9c07-11d1-f79f-00c04fc2dcd2}", //DS-Replication-Get-Changes
    "{89e95b76-444d-4c62-991a-0facbeda640c}", //DS-Replication-Get-Changes-In-Filtered-Set
    "{9923a32a-3607-11d2-b9be-0000f87a36b2}"  //DS-Install-Replica
    //"{19195a5b-6da0-11d0-afd3-00c04fd930c9}", //Domain-DNS class WRITE_DAC
    //"{1131f6ab-9c07-11d1-f79f-00c04fc2dcd2}", //DS-Replication-Synchronize'
    //"{1131f6ac-9c07-11d1-f79f-00c04fc2dcd2}"  //DS-Replication-Manage-Topology'
    )
| project-away TargetLogonId, IpAddress
| lookup kind=leftouter (
    SecurityEvent
    | where ingestion_time() > ago(query_period)
    | where EventID == 4624 and AccountType != "Machine" and LogonType == 3
    | distinct
        Computer,
        TargetLogonId,
        Logon_Account = Account,
        IpAddress
    ) on Computer, $left.SubjectLogonId == $right.TargetLogonId
// If Account was not registered, substitute by Logon_Account
| extend Account = iff(Account == @"-\-", Logon_Account, Account)
// Remove expected DS replications
| join kind=leftanti _BenignDSReplication on IpAddress, Account
| summarize
    arg_min(TimeGenerated, AccountType, Activity, AccessList, AccessMask, ObjectServer, ObjectType, OperationType, Logon_Account),
    OperationCount = count(),
    PropertiesList = array_sort_asc(make_set(split(replace_string(Properties, "\t", ""), " "))),
    SubjectLogonIdsSample = make_set(SubjectLogonId, 25)
    by Computer, Account, IpAddress, ObjectName
// Events where logon was not registered, thus IpAddress is not available, are assumed to be benign and happen infrequently
| where not(isempty(IpAddress) and OperationCount < replication_threshold and Account in (toscalar(_BenignDSReplication | summarize make_set(Account))))
| project
    TimeGenerated,
    Computer,
    Account,
    AccountType,
    Activity,
    AccessList,
    AccessMask,
    ObjectServer,
    ObjectType,
    ObjectName,
    OperationType,
    OperationCount,
    PropertiesList,
    SubjectLogonIdsSample,
    Logon_Account,
    IpAddress

Explanation

This KQL query is designed to detect potentially suspicious Directory Service (DS) replication activities by analyzing security events in a specified time frame. Here's a simplified breakdown of what the query does:

  1. Set Parameters:

    • query_frequency: How often the query checks for events (every 15 minutes).
    • query_period: The total time span of events to consider (3 hours).
    • query_wait: A delay period before checking events (30 minutes).
    • replication_threshold: A threshold for the number of operations considered normal (10).
  2. Identify Expected Activities:

    • It retrieves a list of expected DS replication activities from a watchlist called "Activity-ExpectedSignificantActivity".
  3. Filter Security Events:

    • It looks at security events (EventID 4662) related to DS replication activities, excluding those initiated by machine accounts.
    • It focuses on specific DS replication permissions, such as "DS-Replication-Get-Changes-All".
  4. Match Logon Events:

    • It attempts to match these DS replication events with logon events (EventID 4624) to identify the user accounts and IP addresses involved.
  5. Exclude Benign Activities:

    • It removes events that match the expected benign DS replication activities from the analysis.
  6. Summarize and Filter Results:

    • It summarizes the remaining events by computer, account, IP address, and object name, counting the number of operations and listing unique properties and logon IDs.
    • It filters out events that are assumed to be benign due to the absence of an IP address and a low operation count.
  7. Output:

    • The query outputs a list of potentially suspicious DS replication activities, including details such as the time generated, computer, account, activity type, and associated properties.

In essence, this query helps identify unusual DS replication activities that might indicate unauthorized access or replication attempts, while filtering out expected and benign activities.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: February 18, 2025

Tables

SecurityEvent

Keywords

SecurityEventAccountIpAddressComputerObjectServerObjectTypeOperationTypeActivityAccessListAccessMaskObjectNamePropertiesListSubjectLogonIdsSampleLogonAccount

Operators

let|wherebetweenagohas_anyproject-awaylookupkind=leftouterdistinctonextendiffjoinkind=leftantisummarizearg_mincountarray_sort_ascmake_setsplitreplace_stringisemptytoscalarproject

Actions

GitHub