↳ Source GitHubRègle analytiqueHigh

Local Admin Group Changes

Description

This query searches for changes to the local administrators group. Blogpost: https://www.verboon.info/2020/09/hunting-for-local-group-membership-changes.
Type de règle
Scheduled
Version
1.0.2
Statut déclaré
Available
Fréquence
1h
Période analysée
1h
Déclenchement
gt 0

Couverture MITRE déclarée

Sources déclarées

Métadonnées du fichier source. Aucune dépendance déduite du KQL.

Connecteurs

Types de données

Requête KQL

Requête originale, sans modification.

let machineAccountSIDs = dynamic([
  "S-1-5-18",
  "S-1-5-20",
  "S-1-5-19"]);
let ADAZUsers =  IdentityInfo 
| extend DirectoryDomain = AccountDomain 
| extend DirectoryAccount = AccountName 
| extend OnPremSid = AccountSID
| distinct DirectoryDomain , DirectoryAccount , OnPremSid , AccountCloudSID, AccountUPN, GivenName, Surname;
 // check for any new created or modified local accounts 
let NewUsers =  DeviceEvents
| where ActionType contains "UserAccountCreated" or ActionType contains "UserAccountModified"
| extend lUserAdded = AccountName
| extend NewUserSID = AccountSid
| extend laccountdomain = AccountDomain
| distinct NewUserSID, lUserAdded,laccountdomain;
// Check for any local group changes and enrich the data with the account name obtained from the previous query
DeviceEvents 
| where ActionType == 'UserAccountAddedToLocalGroup'
// Exclude machine and wellknown SIDs 
| where (AccountSid !in (machineAccountSIDs)) and (AccountSid matches regex @"S-\d-\d+-\d+-(\d+-){1,5}\d+")
| extend LocalGroupSID = tostring(parse_json(AdditionalFields).GroupSid)
| extend LocalGroup = tostring(parse_json(AdditionalFields).GroupName)
| extend AddedAccountSID = AccountSid
| extend Actor = trim(@"[^\w]+",InitiatingProcessAccountName)
// limit to local administrators group
// | where LocalGroupSID contains "S-1-5-32-544"
| join kind=leftouter    (NewUsers)
on $left.AddedAccountSID == $right.NewUserSID
| project TimeGenerated, DeviceName, LocalGroup,LocalGroupSID, AddedAccountSID, lUserAdded , Actor, ActionType , laccountdomain 
| join kind=innerunique  (ADAZUsers)
on $left.AddedAccountSID == $right.OnPremSid
| extend UserAdded = iff(isnotempty(lUserAdded),strcat(laccountdomain,"\\", lUserAdded), strcat(DirectoryDomain,"\\", DirectoryAccount))
| extend AccountName = iff(isnotempty(lUserAdded), lUserAdded, DirectoryAccount)
| project TimeGenerated, DeviceName, LocalGroup, LocalGroupSID, AddedAccountSID, UserAdded ,Actor, ActionType, AccountName, laccountdomain  
| where DeviceName !contains Actor
// Provide details on actors that added users
// | summarize count()  by Actor 
// | join ADAZUsers
// on $left.Actor == $right.DirectoryAccount 
// | render piechart
| extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
| extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")

Entités déclarées

HostAccount

Contenus associés

Liens établis à partir des identifiants déclarés et des manifests des solutions.

Traçabilité de la source

GitHub

Les valeurs affichées proviennent des fichiers du dépôt Azure/Azure-Sentinel. Elles décrivent le modèle publié, pas la configuration de votre workspace.

Identifiant source
63aa43c2-e88e-4102-aea5-0432851c541a
Autres fichiers source 2Solutions/Microsoft Defender XDR/Analytic Rules/Persistence/LocalAdminGroupChanges.yamlsource ↗Solutions/Microsoft Defender XDR/Data/Solution_Microsoft Defender XDR.jsonsolution-membership ↗
GSTEP / SUIVI DU CATALOGUE

Ajouté au catalogue : 16 sept. 2026 · 05:49 UTC
Dernier changement observé : 16 sept. 2026 · 05:49 UTC

Dates de synchronisation GSTEP, distinctes des dates de publication du contenu source.