Detection rules › Kusto

New user created and added to the built-in administrators group

Severity
low
Time window
1d
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

Identifies when a user account was created and then added to the builtin Administrators group in the same day. This should be monitored closely and all additions reviewed.

MITRE ATT&CK coverage

Event coverage

Rule body kusto

id: aa1eff90-29d4-49dc-a3ea-b65199f516db
name: New user created and added to the built-in administrators group
description: |
  'Identifies when a user account was created and then added to the builtin Administrators group in the same day.
  This should be monitored closely and all additions reviewed.'
severity: Low
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
     - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes: 
      - SecurityEvents 
  - connectorId: WindowsForwardedEvents
    dataTypes: 
      - WindowsEvent 
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
  - PrivilegeEscalation
relevantTechniques:
  - T1098
  - T1078
query: |
  (union isfuzzy=true
      (SecurityEvent
      | where EventID == 4720
      | where AccountType == "User"
      | project CreatedUserTime = TimeGenerated, CreatedUserEventID = EventID, CreatedUserActivity = Activity, Computer = toupper(Computer), 
      CreatedUser = tolower(TargetAccount), CreatedUserAccountName = TargetUserName, CreatedUserDomainName = TargetDomainName, CreatedUserSid = TargetSid, 
      AccountUsedToCreateUser = SubjectAccount, CreatedByAccountName = SubjectUserName, CreatedByDomainName = SubjectDomainName, SidofAccountUsedToCreateUser = SubjectUserSid
      ),
      (WindowsEvent
      | where EventID == 4720
      | extend SubjectUserSid = tostring(EventData.SubjectUserSid)
      | extend AccountType=case(EventData.SubjectUserName endswith "$" or SubjectUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(SubjectUserSid), "", "User")
      | where AccountType == "User"
      | extend SubjectAccount = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
      | extend SubjectDomainName = tostring(EventData.SubjectDomainName), SubjectUserName = tostring(EventData.SubjectUserName)
      | extend TargetAccount = strcat(EventData.TargetDomainName,"\\", EventData.TargetUserName)
      | extend TargetUserName = tostring(EventData.TargetUserName), TargetDomainName = tostring(EventData.TargetDomainName) 
      | extend Activity="4720 - A user account was created."
      | extend TargetSid = tostring(EventData.TargetSid)
      | project CreatedUserTime = TimeGenerated, CreatedUserEventID = EventID, CreatedUserActivity = Activity, Computer = toupper(Computer), 
      CreatedUser = tolower(TargetAccount), CreatedUserAccountName = TargetUserName, CreatedUserDomainName = TargetDomainName, CreatedUserSid = TargetSid, 
      AccountUsedToCreateUser = SubjectAccount, CreatedByAccountName = SubjectUserName, CreatedByDomainName = SubjectDomainName, SidofAccountUsedToCreateUser = SubjectUserSid
      )
    )
  | join kind=inner
  (
    (union isfuzzy=true
      (SecurityEvent 
      | where AccountType == "User"
      // 4732 - A member was added to a security-enabled local group
      | where EventID == 4732
      // TargetSid is the builin Admins group: S-1-5-32-544
      | where TargetSid == "S-1-5-32-544"
      | project GroupAddTime = TimeGenerated, GroupAddEventID = EventID, GroupAddActivity = Activity, Computer = toupper(Computer), GroupName = tolower(TargetAccount), 
      GroupSid = TargetSid, AccountThatAddedUser = SubjectAccount, SIDofAccountThatAddedUser = SubjectUserSid, AddedByAccountName = SubjectUserName, AddedByDomainName = SubjectDomainName,
      CreatedUserSid = MemberSid
      ),
      (  WindowsEvent 
      // 4732 - A member was added to a security-enabled local group
      | where EventID == 4732 and EventData has "S-1-5-32-544"
      //TargetSid is the builin Admins group: S-1-5-32-544
      | extend SubjectUserSid = tostring(EventData.SubjectUserSid)
      | extend AccountType=case(EventData.SubjectUserName endswith "$" or SubjectUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(SubjectUserSid), "", "User")
      | where AccountType == "User"
      | extend TargetSid = tostring(EventData.TargetSid)
      | where TargetSid == "S-1-5-32-544"
      | extend SubjectAccount = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
      | extend SubjectDomainName = tostring(EventData.SubjectDomainName), SubjectUserName = tostring(EventData.SubjectUserName)
      | extend TargetAccount = strcat(EventData.TargetDomainName,"\\", EventData.TargetUserName)
      | extend Activity="4732 - A member was added to a security-enabled local group."
      | extend MemberSid = tostring(EventData.MemberSid)
      | project GroupAddTime = TimeGenerated, GroupAddEventID = EventID, GroupAddActivity = Activity, Computer = toupper(Computer), GroupName = tolower(TargetAccount), 
      GroupSid = TargetSid, AccountThatAddedUser = SubjectAccount, SIDofAccountThatAddedUser = SubjectUserSid, AddedByAccountName = SubjectUserName, AddedByDomainName = SubjectDomainName,
      CreatedUserSid = MemberSid
      )
    )
  )
  on CreatedUserSid
  //Create User first, then the add to the group.
  | project Computer, CreatedUserTime, CreatedUserEventID, CreatedUserActivity, CreatedUser, CreatedUserSid, CreatedUserAccountName, CreatedUserDomainName,
  GroupAddTime, GroupAddEventID, GroupAddActivity, GroupName, GroupSid,
  AccountUsedToCreateUser, SidofAccountUsedToCreateUser, CreatedByAccountName, CreatedByDomainName, 
  AccountThatAddedUser, SIDofAccountThatAddedUser, AddedByAccountName, AddedByDomainName
  | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
  | project-away DomainIndex
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountUsedToCreateUser
      - identifier: Name
        columnName: CreatedByAccountName
      - identifier: NTDomain
        columnName: CreatedByDomainName
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountThatAddedUser
      - identifier: Name
        columnName: AddedByAccountName
      - identifier: NTDomain
        columnName: AddedByDomainName
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: CreatedUser
      - identifier: Name
        columnName: CreatedUserAccountName
      - identifier: NTDomain
        columnName: CreatedUserDomainName
  - entityType: Account
    fieldMappings:
      - identifier: Sid
        columnName: CreatedUserSid
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: NTDomain
        columnName: HostNameDomain
version: 1.2.1
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Others", "Identity" ]

Stages and Predicates

union isfuzzy=true (2 sources)

Each leg below queries one source; the rule matches if any leg does. Sources: SecurityEvent, WindowsEvent

Leg 1: SecurityEvent

SecurityEvent
    | where EventID == 4720
    | where AccountType == "User"
    | project CreatedUserTime = TimeGenerated, CreatedUserEventID = EventID, CreatedUserActivity = Activity, Computer = toupper(Computer), 
    CreatedUser = tolower(TargetAccount), CreatedUserAccountName = TargetUserName, CreatedUserDomainName = TargetDomainName, CreatedUserSid = TargetSid, 
    AccountUsedToCreateUser = SubjectAccount, CreatedByAccountName = SubjectUserName, CreatedByDomainName = SubjectDomainName, SidofAccountUsedToCreateUser = SubjectUserSid

Leg 2: WindowsEvent

WindowsEvent
    | where EventID == 4720
    | extend SubjectUserSid = tostring(EventData.SubjectUserSid)
    | extend AccountType=case(EventData.SubjectUserName endswith "$" or SubjectUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(SubjectUserSid), "", "User")
    | where AccountType == "User"
    | extend SubjectAccount = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
    | extend SubjectDomainName = tostring(EventData.SubjectDomainName), SubjectUserName = tostring(EventData.SubjectUserName)
    | extend TargetAccount = strcat(EventData.TargetDomainName,"\\", EventData.TargetUserName)
    | extend TargetUserName = tostring(EventData.TargetUserName), TargetDomainName = tostring(EventData.TargetDomainName) 
    | extend Activity="4720 - A user account was created."
    | extend TargetSid = tostring(EventData.TargetSid)
    | project CreatedUserTime = TimeGenerated, CreatedUserEventID = EventID, CreatedUserActivity = Activity, Computer = toupper(Computer), 
    CreatedUser = tolower(TargetAccount), CreatedUserAccountName = TargetUserName, CreatedUserDomainName = TargetDomainName, CreatedUserSid = TargetSid, 
    AccountUsedToCreateUser = SubjectAccount, CreatedByAccountName = SubjectUserName, CreatedByDomainName = SubjectDomainName, SidofAccountUsedToCreateUser = SubjectUserSid

Applied to the combined result

| join kind=inner
(
  (union isfuzzy=true
    (SecurityEvent 
    | where AccountType == "User"
    | where EventID == 4732
    | where TargetSid == "S-1-5-32-544"
    | project GroupAddTime = TimeGenerated, GroupAddEventID = EventID, GroupAddActivity = Activity, Computer = toupper(Computer), GroupName = tolower(TargetAccount), 
    GroupSid = TargetSid, AccountThatAddedUser = SubjectAccount, SIDofAccountThatAddedUser = SubjectUserSid, AddedByAccountName = SubjectUserName, AddedByDomainName = SubjectDomainName,
    CreatedUserSid = MemberSid
    ),
    (  WindowsEvent 
    | where EventID == 4732 and EventData has "S-1-5-32-544"
    | extend SubjectUserSid = tostring(EventData.SubjectUserSid)
    | extend AccountType=case(EventData.SubjectUserName endswith "$" or SubjectUserSid in ("S-1-5-18", "S-1-5-19", "S-1-5-20"), "Machine", isempty(SubjectUserSid), "", "User")
    | where AccountType == "User"
    | extend TargetSid = tostring(EventData.TargetSid)
    | where TargetSid == "S-1-5-32-544"
    | extend SubjectAccount = strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
    | extend SubjectDomainName = tostring(EventData.SubjectDomainName), SubjectUserName = tostring(EventData.SubjectUserName)
    | extend TargetAccount = strcat(EventData.TargetDomainName,"\\", EventData.TargetUserName)
    | extend Activity="4732 - A member was added to a security-enabled local group."
    | extend MemberSid = tostring(EventData.MemberSid)
    | project GroupAddTime = TimeGenerated, GroupAddEventID = EventID, GroupAddActivity = Activity, Computer = toupper(Computer), GroupName = tolower(TargetAccount), 
    GroupSid = TargetSid, AccountThatAddedUser = SubjectAccount, SIDofAccountThatAddedUser = SubjectUserSid, AddedByAccountName = SubjectUserName, AddedByDomainName = SubjectDomainName,
    CreatedUserSid = MemberSid
    )
  )
)
on CreatedUserSid
| project Computer, CreatedUserTime, CreatedUserEventID, CreatedUserActivity, CreatedUser, CreatedUserSid, CreatedUserAccountName, CreatedUserDomainName,
GroupAddTime, GroupAddEventID, GroupAddActivity, GroupName, GroupSid,
AccountUsedToCreateUser, SidofAccountUsedToCreateUser, CreatedByAccountName, CreatedByDomainName, 
AccountThatAddedUser, SIDofAccountThatAddedUser, AddedByAccountName, AddedByDomainName
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| project-away DomainIndex

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
AccountTypeeq
  • User transforms: cased corpus 9 (kusto 9)
EventDatamatch
  • S-1-5-32-544 transforms: term
EventIDeq
  • 4720 transforms: cased corpus 5 (kusto 3, splunk 2)
  • 4732 transforms: cased corpus 4 (splunk 3, kusto 1)
TargetSideq
  • S-1-5-32-544 transforms: cased corpus 3 (sigma 2, kusto 1)

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
AccountThatAddedUserproject
AccountUsedToCreateUserproject
AddedByAccountNameproject
AddedByDomainNameproject
Computerproject
CreatedByAccountNameproject
CreatedByDomainNameproject
CreatedUserproject
CreatedUserAccountNameproject
CreatedUserActivityproject
CreatedUserDomainNameproject
CreatedUserEventIDproject
CreatedUserSidproject
CreatedUserTimeproject
GroupAddActivityproject
GroupAddEventIDproject
GroupAddTimeproject
GroupNameproject
GroupSidproject
SIDofAccountThatAddedUserproject
SidofAccountUsedToCreateUserproject
HostNameextend
HostNameDomainextend