Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Azure DevOps Administrator Group Monitoring

Back
Id89e6adbd-612c-4fbe-bc3d-32f81baf3b6c
RulenameAzure DevOps Administrator Group Monitoring
DescriptionThis detection monitors for additions to projects or project collection administration groups in an Azure DevOps Organization.
SeverityMedium
TacticsPersistence
TechniquesT1098
KindScheduled
Query frequency4h
Query period4h
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureDevOpsAuditing/Analytic Rules/AzDOAdminGroupAdditions.yaml
Version1.0.5
Arm template89e6adbd-612c-4fbe-bc3d-32f81baf3b6c.json
Deploy To Azure
// Change to true to monitor for Project Administrator adds to *any* project
let MonitorAllProjects = false;
// If MonitorAllProjects is false, trigger only on Project Administrator add for the following projects
let ProjectsToMonitor = dynamic(['<project_X>','<project_Y>']);
ADOAuditLogs
| where Area == "Group" and OperationName == "Group.UpdateGroupMembership.Add"
| where Details has 'Administrators'
| where Details has "was added as a member of group" and (Details endswith '\\Project Administrators' or Details endswith '\\Project Collection Administrators')
| parse Details with AddedIdentity ' was added as a member of group [' EntityName ']\\' GroupName
| extend Level = iif(GroupName == 'Project Collection Administrators', 'Organization', 'Project'), AddedIdentityId = Data.MemberId
| extend Severity = iif(Level == 'Organization', 'High', 'Medium'), AlertDetails = strcat('At ', TimeGenerated, ' UTC ', ActorUPN, '/', ActorDisplayName, ' added ', AddedIdentity, ' to the ', EntityName, ' ', Level)
| where MonitorAllProjects == true or EntityName in (ProjectsToMonitor) or Level == 'Organization'
| project TimeGenerated, Severity, Adder = ActorUPN, AddedIdentity, AddedIdentityId, AlertDetails, Level, EntityName, GroupName, ActorAuthType = AuthenticationMechanism,
  ActorIpAddress = IpAddress, ActorUserAgent = UserAgent, RawDetails = Details
| extend timestamp = TimeGenerated
| extend AccountName = tostring(split(Adder, "@")[0]), AccountUPNSuffix = tostring(split(Adder, "@")[1])
description: |
    'This detection monitors for additions to projects or project collection administration groups in an Azure DevOps Organization.'
kind: Scheduled
tactics:
- Persistence
requiredDataConnectors: []
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureDevOpsAuditing/Analytic Rules/AzDOAdminGroupAdditions.yaml
severity: Medium
name: Azure DevOps Administrator Group Monitoring
triggerThreshold: 0
queryPeriod: 4h
query: |
  // Change to true to monitor for Project Administrator adds to *any* project
  let MonitorAllProjects = false;
  // If MonitorAllProjects is false, trigger only on Project Administrator add for the following projects
  let ProjectsToMonitor = dynamic(['<project_X>','<project_Y>']);
  ADOAuditLogs
  | where Area == "Group" and OperationName == "Group.UpdateGroupMembership.Add"
  | where Details has 'Administrators'
  | where Details has "was added as a member of group" and (Details endswith '\\Project Administrators' or Details endswith '\\Project Collection Administrators')
  | parse Details with AddedIdentity ' was added as a member of group [' EntityName ']\\' GroupName
  | extend Level = iif(GroupName == 'Project Collection Administrators', 'Organization', 'Project'), AddedIdentityId = Data.MemberId
  | extend Severity = iif(Level == 'Organization', 'High', 'Medium'), AlertDetails = strcat('At ', TimeGenerated, ' UTC ', ActorUPN, '/', ActorDisplayName, ' added ', AddedIdentity, ' to the ', EntityName, ' ', Level)
  | where MonitorAllProjects == true or EntityName in (ProjectsToMonitor) or Level == 'Organization'
  | project TimeGenerated, Severity, Adder = ActorUPN, AddedIdentity, AddedIdentityId, AlertDetails, Level, EntityName, GroupName, ActorAuthType = AuthenticationMechanism,
    ActorIpAddress = IpAddress, ActorUserAgent = UserAgent, RawDetails = Details
  | extend timestamp = TimeGenerated
  | extend AccountName = tostring(split(Adder, "@")[0]), AccountUPNSuffix = tostring(split(Adder, "@")[1])  
relevantTechniques:
- T1098
id: 89e6adbd-612c-4fbe-bc3d-32f81baf3b6c
queryFrequency: 4h
status: Available
triggerOperator: gt
version: 1.0.5
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: Adder
    identifier: FullName
  - columnName: AccountName
    identifier: Name
  - columnName: AccountUPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: ActorIpAddress
    identifier: Address