Query Details

Function Group Changes

Query

// Save as a function in your workspace then invoke via its name, i.e if you save as GroupChanges
// GroupChanges | where TimeGenerated > ago(1d) | where Action == "Add" and GroupName == "TestGroup1" // Will find all group additions to "TestGroup1"
// GroupChanges | where TimeGenerated > ago(1d) | where Action == "Remove" and Actor == "User1" and Environment == "Azure Active Directory" // will find all group removals by "User1" in Azure Active Directory
// GroupChanges | where TimeGenerated > ago(1d) | where Action == "Add" | Will find all Add actions in both Active Directory and Azure Active Directory
let aaduseradded=
    AuditLogs
    | where OperationName == "Add member to group"
    | extend Actor = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
    | extend Target = tostring(TargetResources[0].userPrincipalName)
    | extend GroupName = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[1].newValue)))
    | where isnotempty(Actor) and isnotempty(Target)
    | extend Environment = strcat("Azure Active Directory")
    | extend Action = strcat("Add")
    | project TimeGenerated, Action, Actor, Target, GroupName, Environment;
let aaduserremoved=
    AuditLogs
    | where OperationName == "Remove member from group"
    | extend Actor = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
    | extend GroupName = tostring(parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[1].oldValue)))
    | extend Target = tostring(TargetResources[0].userPrincipalName)
    | where isnotempty(Actor) and isnotempty(Target)
    | extend Action = strcat("Remove")
    | extend Environment = strcat("Azure Active Directory")
    | project TimeGenerated, Action, Actor, Target, GroupName, Environment;
let adchanges=
    SecurityEvent
    | project TimeGenerated, EventID, AccountType, MemberName, SubjectUserName, TargetUserName
    | where AccountType == "User"
    | where EventID in (4728, 4729, 4732, 4733, 4756, 4757)
    | extend x = tolower(MemberName)
    | parse x with * 'cn=' Target ',ou=' *
    | extend Action = case(EventID in ("4728", "4756", "4732"), strcat("Add"),
        EventID in ("4729", "4757", "4733"), strcat("Remove"), "unknown")
    | extend Environment = strcat("Active Directory")
    | project TimeGenerated, Action, Actor=SubjectUserName, Target, GroupName=TargetUserName, Environment;
union aaduseradded, aaduserremoved, adchanges

Explanation

The query is searching for changes made to groups in both Azure Active Directory and Active Directory. It looks for additions and removals of members from groups, as well as changes to group properties. The query retrieves information such as the time the change occurred, the action (add or remove), the actor who made the change, the target member or group, and the environment (Azure Active Directory or Active Directory). The results from the Azure Active Directory and Active Directory queries are combined using the "union" operator.

Details

Matt Zorich profile picture

Matt Zorich

Released: May 4, 2022

Tables

AuditLogsSecurityEvent

Keywords

Devices,Intune,User,AuditLogs,InitiatedBy,TargetResources,TimeGenerated,Action,Actor,Target,GroupName,Environment,SecurityEvent,EventID,AccountType,MemberName,SubjectUserName,TargetUserName,x,cn,ou

Operators

whereextendtostringparse_jsonisnotemptystrcatprojectunion

Actions