Query Details

Defender for Endpoint - Local Built-in Group Membership additions

MDE Windows Built In Group Member Changes

Query

let DirectoryIdentities = (IdentityInfo
| where Timestamp > ago(21d)
| summarize arg_max(Timestamp,*) by AccountUpn
| project AccountDisplayName, AccountObjectId,OnPremSid, AccountDomain, AccountName);
let DomainIdentifiers = (DirectoryIdentities
| where isnotempty(OnPremSid)
| extend DomainIdentifier = extract("S-1-5-21-(\\d+-\\d+-\\d+)-\\d+", 1, OnPremSid)
| distinct DomainIdentifier);
let LocalAccounts = (DeviceEvents
| where Timestamp > ago(30d)
| where ActionType == @"UserAccountCreated"
| extend LocalAccountSid = AccountSid
| extend LocalAccountName = AccountName
| extend LocalAccountDomain = AccountDomain
| extend LocalDeviceName = split(DeviceName,".")[0]
| where LocalAccountDomain == LocalDeviceName
| project LocalAccountSid, LocalAccountName, LocalAccountDomain, LocalDeviceName);
let SensitiveBuiltInGroups = datatable(GroupsSID: string,BuildInGroupName: string)
[
"S-1-5-32-544","Administrtors",
"S-1-5-32-546","Guests",
"S-1-5-32-547","Power Users",
"S-1-5-32-555","Remote Desktop Users",
"S-1-5-32-580","Remote Management Users",
];
SensitiveBuiltInGroups
| join kind=inner (
DeviceEvents
| where ActionType == 'UserAccountAddedToLocalGroup'
| extend AccoundSIDAdded = AccountSid
| extend ChangedGroupSid = tostring(parse_json(AdditionalFields).GroupSid)
| extend ChangedGroupName = tostring(parse_json(AdditionalFields).GroupName)
| extend ChangedGroupDomainName = tostring(parse_json(AdditionalFields).GroupDomainName)
| extend ActorSID = InitiatingProcessAccountSid
| extend ActorAccountName = InitiatingProcessAccountName
| extend ActorDomain = InitiatingProcessAccountDomain
| where InitiatingProcessAccountSid <> "S-1-5-18" // exclude actions from local system account
)
on $left.GroupsSID == $right.ChangedGroupSid
| join kind=leftouter (DirectoryIdentities) on $left.AccoundSIDAdded == $right.OnPremSid
| extend AccountNameAdded = AccountName1
| extend AccountDomainAdded = AccountDomain1
| extend AccountDisplayNameAdded = AccountDisplayName
| extend AccountSource = iff(AccoundSIDAdded has_any (DomainIdentifiers), "AD",iff(AccoundSIDAdded startswith "S-1-12-1","EntraID","local"))
| extend ActorAccountType = iff(ActorDomain == split(DeviceName,".")[0],"local",iff(ActorDomain == 'azuread',"EntraID","AD"))
| join kind=leftouter LocalAccounts
on $left. AccoundSIDAdded == $right.LocalAccountSid
| extend  AccountNameAdded = iff(isnotempty(LocalAccountSid),LocalAccountName, AccountNameAdded)
| extend  AccountDomainAdded = iff(isnotempty(LocalAccountSid),LocalAccountDomain, AccountDomainAdded)
| project Timestamp, DeviceName, AccoundSIDAdded,AccountSource, AccountNameAdded, AccountDomainAdded, ChangedGroupName, ChangedGroupSid, ChangedGroupDomainName, ActorAccountName, ActorDomain,ActorAccountType,ActorSID

About this query

Explanation

This query is designed to identify when new user accounts are added to built-in local groups on Windows devices, which can be a sign of account manipulation or unauthorized access. It uses data from Microsoft Defender XDR and Microsoft Sentinel to track these changes. Here's a simplified breakdown of what the query does:

  1. Data Collection:

    • It gathers information about user accounts from the IdentityInfo table, focusing on recent data (from the last 21 days).
    • It also collects events related to user account creation from the DeviceEvents table, looking at the last 30 days.
  2. Identify Domain and Local Accounts:

    • It extracts domain identifiers from user account data.
    • It identifies local accounts by checking if the account domain matches the device name.
  3. Sensitive Groups:

    • It defines a list of sensitive built-in groups, such as Administrators, Guests, Power Users, Remote Desktop Users, and Remote Management Users.
  4. Join and Filter Events:

    • It joins the sensitive groups with events where a user account is added to a local group.
    • It filters out actions performed by the local system account to focus on potentially unauthorized changes.
  5. Account Source and Actor Information:

    • It determines the source of the account (Active Directory, EntraID, or local).
    • It identifies the type of account making the change (local, EntraID, or AD).
  6. Output:

    • The query outputs details such as the timestamp, device name, account added, group changed, and the actor who made the change.

The query is slightly different for Microsoft Defender XDR and Microsoft Sentinel due to differences in the IdentityInfo table structure, but the overall logic and purpose remain the same.

Details

Alex Verboon profile picture

Alex Verboon

Released: March 25, 2024

Tables

IdentityInfoDeviceEvents

Keywords

DefenderEndpointDevicesAccountsSecurityUsers

Operators

letwhereagosummarizearg_maxbyprojectisnotemptyextendextractdistinctdatatablejoinkindinnerparse_jsontostringiffhas_anystartswithsplitleftouter

MITRE Techniques

Actions

GitHub