Query Details
let query_frequency = 1h;
let query_period = 14d;
let wait_for_addition = 30m;
let _DomainGroups =
_GetWatchlist("SID-AuditDomainGroups")
| where Notes has "[Removal]"
| project GroupSID, SAMAccountName, Auditor, Severity, Notes
;
SecurityEvent
| where TimeGenerated > ago(query_frequency + wait_for_addition)
| where EventID in (4728, 4732, 4756, 4729, 4733, 4757)
| lookup kind=inner _DomainGroups on $left.TargetSid == $right.GroupSID
| extend MemberAccount = extract("[Cc][Nn]=([^,]*).*$", 1, MemberName)
| summarize
GroupAddition_TimeGenerated = maxif(TimeGenerated, EventID in (4728, 4732, 4756)),
GroupRemoval_TimeGenerated = maxif(TimeGenerated, EventID in (4729, 4733, 4757)),
arg_max(TimeGenerated, *)
by MemberSid, MemberAccount
| where GroupRemoval_TimeGenerated between (ago(query_frequency + wait_for_addition) .. ago(wait_for_addition))
| where not(isnotempty(GroupAddition_TimeGenerated) and GroupAddition_TimeGenerated > GroupRemoval_TimeGenerated)
| join kind=leftouter (
SecurityEvent
| where TimeGenerated > ago(query_period)
| where EventID in (4722, 4725, 4726)
| summarize
AccountEnable_TimeGenerated = maxif(TimeGenerated, EventID == 4722),
AccountDisable_TimeGenerated = maxif(TimeGenerated, EventID == 4725),
AccountDeletion_TimeGenerated = maxif(TimeGenerated, EventID == 4726)
by TargetSid
) on $left.MemberSid == $right.TargetSid
// Custom exclusions
| where isempty(AccountDeletion_TimeGenerated)
| where not(isnotempty(AccountDisable_TimeGenerated) and isnotempty(AccountEnable_TimeGenerated) and AccountDisable_TimeGenerated > GroupRemoval_TimeGenerated and AccountDisable_TimeGenerated > AccountEnable_TimeGenerated)
| where not(isnotempty(AccountDisable_TimeGenerated) and isempty(AccountEnable_TimeGenerated) and AccountDisable_TimeGenerated > GroupRemoval_TimeGenerated)
| project
TimeGenerated,
Computer,
ActorAccount = Account,
Activity = trim_end(@"\.", Activity),
GroupName = TargetUserName,
MemberAccount,
GroupAddition_TimeGenerated,
GroupRemoval_TimeGenerated,
AccountEnable_TimeGenerated,
AccountDisable_TimeGenerated,
AccountDeletion_TimeGenerated,
ActorAccountSid = SubjectUserSid,
GroupSid = TargetSid,
MemberSid,
AlertSeverity = Severity,
Auditor,
Notes,
EventData
This query is designed to monitor changes in domain groups within a security system. It checks every hour for the past 14 days and waits for 30 minutes before adding new data.
The query first retrieves a list of domain groups that have had a removal event. It then checks the security event logs for specific event IDs that correspond to group addition and removal events.
For each member of the domain groups, the query records the time of the latest group addition and removal events. It then filters out any group removal events that occurred within the last hour to 30 minutes ago.
The query also checks if a group addition event occurred after a group removal event and excludes these cases.
Next, the query joins this data with another set of security event logs that record account enable, disable, and deletion events. It records the latest time of each of these events for each member.
Finally, the query excludes cases where an account was deleted, or an account was disabled after it was removed from a group. It also excludes cases where an account was disabled but not re-enabled after it was removed from a group.
The result is a detailed report of domain group changes, including the time of each event, the computer where the event occurred, the account that performed the action, the group name, the member account, and other relevant information.

Jose Sebastián Canós
Released: October 31, 2022
Tables
Keywords
Operators