let max_owner_count = 3;
// Adjust this value to change how many teams a user is made owner of before detecting
// OfficeActivity Query: Identify users who have been made owners of more than 'max_owner_count' teams
let high_owner_count_office = (
OfficeActivity
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRoleChanged"
| extend Member = tostring(parse_json(Members)[0].UPN)
| extend NewRole = toint(parse_json(Members)[0].Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| summarize TeamCount = dcount(TeamName) by Member
| where TeamCount > max_owner_count
| project Member
);
// OfficeActivity Query: Fetch details for users with high ownership count
let OfficeEvents = OfficeActivity
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRoleChanged"
| extend Member = tostring(parse_json(Members)[0].UPN)
| extend NewRole = toint(parse_json(Members)[0].Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| where Member in (high_owner_count_office)
| extend AccountName = tostring(split(Member, "@")[0]), AccountUPNSuffix = tostring(split(Member, "@")[1]);
// EnrichedMicrosoft365AuditLogs Query: Identify users who have been made owners of more than 'max_owner_count' teams
let high_owner_count_enriched = (
EnrichedMicrosoft365AuditLogs
| where Workload == "MicrosoftTeams"
| where Operation == "MemberRoleChanged"
| extend Member = tostring(UserId)
| extend NewRole = toint(parse_json(tostring(AdditionalProperties)).Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| summarize TeamCount = dcount(ObjectId) by Member
| where TeamCount > max_owner_count
| project Member
);
// EnrichedMicrosoft365AuditLogs Query: Fetch details for users with high ownership count
let EnrichedEvents = EnrichedMicrosoft365AuditLogs
| where Workload == "MicrosoftTeams"
| where Operation == "MemberRoleChanged"
| extend Member = tostring(UserId)
| extend NewRole = toint(parse_json(tostring(AdditionalProperties)).Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| where Member in (high_owner_count_enriched)
| extend AccountName = tostring(split(Member, "@")[0]), AccountUPNSuffix = tostring(split(Member, "@")[1]);
// Combine Office and Enriched Logs
let CombinedEvents = OfficeEvents
| union EnrichedEvents
| summarize by Member, AccountName, AccountUPNSuffix;
// Final Output
CombinedEvents
| order by Member asc
| project Member, AccountName, AccountUPNSuffix
name: GSA Enriched Office 365 - User made Owner of multiple teams
version: 2.0.2
id: 558f15dd-3171-4b11-bf24-31c0610a20e0
tactics:
- PrivilegeEscalation
query: |
let max_owner_count = 3;
// Adjust this value to change how many teams a user is made owner of before detecting
// OfficeActivity Query: Identify users who have been made owners of more than 'max_owner_count' teams
let high_owner_count_office = (
OfficeActivity
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRoleChanged"
| extend Member = tostring(parse_json(Members)[0].UPN)
| extend NewRole = toint(parse_json(Members)[0].Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| summarize TeamCount = dcount(TeamName) by Member
| where TeamCount > max_owner_count
| project Member
);
// OfficeActivity Query: Fetch details for users with high ownership count
let OfficeEvents = OfficeActivity
| where OfficeWorkload =~ "MicrosoftTeams"
| where Operation =~ "MemberRoleChanged"
| extend Member = tostring(parse_json(Members)[0].UPN)
| extend NewRole = toint(parse_json(Members)[0].Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| where Member in (high_owner_count_office)
| extend AccountName = tostring(split(Member, "@")[0]), AccountUPNSuffix = tostring(split(Member, "@")[1]);
// EnrichedMicrosoft365AuditLogs Query: Identify users who have been made owners of more than 'max_owner_count' teams
let high_owner_count_enriched = (
EnrichedMicrosoft365AuditLogs
| where Workload == "MicrosoftTeams"
| where Operation == "MemberRoleChanged"
| extend Member = tostring(UserId)
| extend NewRole = toint(parse_json(tostring(AdditionalProperties)).Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| summarize TeamCount = dcount(ObjectId) by Member
| where TeamCount > max_owner_count
| project Member
);
// EnrichedMicrosoft365AuditLogs Query: Fetch details for users with high ownership count
let EnrichedEvents = EnrichedMicrosoft365AuditLogs
| where Workload == "MicrosoftTeams"
| where Operation == "MemberRoleChanged"
| extend Member = tostring(UserId)
| extend NewRole = toint(parse_json(tostring(AdditionalProperties)).Role)
| where NewRole == 2 // Role 2 corresponds to "Owner"
| where Member in (high_owner_count_enriched)
| extend AccountName = tostring(split(Member, "@")[0]), AccountUPNSuffix = tostring(split(Member, "@")[1]);
// Combine Office and Enriched Logs
let CombinedEvents = OfficeEvents
| union EnrichedEvents
| summarize by Member, AccountName, AccountUPNSuffix;
// Final Output
CombinedEvents
| order by Member asc
| project Member, AccountName, AccountUPNSuffix
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Hunting Queries/MultiTeamOwner.yaml
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- EnrichedMicrosoft365AuditLogs
relevantTechniques:
- T1078
kind: Scheduled
description: |
This hunting query identifies users who have been made Owner of multiple Teams.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/558f15dd-3171-4b11-bf24-31c0610a20e0')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/558f15dd-3171-4b11-bf24-31c0610a20e0')]",
"properties": {
"alertRuleTemplateName": "558f15dd-3171-4b11-bf24-31c0610a20e0",
"customDetails": null,
"description": "This hunting query identifies users who have been made Owner of multiple Teams.\n",
"displayName": "GSA Enriched Office 365 - User made Owner of multiple teams",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "AccountUPNSuffix",
"identifier": "UPNSuffix"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Global Secure Access/Hunting Queries/MultiTeamOwner.yaml",
"query": "let max_owner_count = 3; \n// Adjust this value to change how many teams a user is made owner of before detecting\n// OfficeActivity Query: Identify users who have been made owners of more than 'max_owner_count' teams\nlet high_owner_count_office = (\n OfficeActivity\n | where OfficeWorkload =~ \"MicrosoftTeams\"\n | where Operation =~ \"MemberRoleChanged\"\n | extend Member = tostring(parse_json(Members)[0].UPN) \n | extend NewRole = toint(parse_json(Members)[0].Role)\n | where NewRole == 2 // Role 2 corresponds to \"Owner\"\n | summarize TeamCount = dcount(TeamName) by Member\n | where TeamCount > max_owner_count\n | project Member\n);\n// OfficeActivity Query: Fetch details for users with high ownership count\nlet OfficeEvents = OfficeActivity\n | where OfficeWorkload =~ \"MicrosoftTeams\"\n | where Operation =~ \"MemberRoleChanged\"\n | extend Member = tostring(parse_json(Members)[0].UPN)\n | extend NewRole = toint(parse_json(Members)[0].Role)\n | where NewRole == 2 // Role 2 corresponds to \"Owner\"\n | where Member in (high_owner_count_office)\n | extend AccountName = tostring(split(Member, \"@\")[0]), AccountUPNSuffix = tostring(split(Member, \"@\")[1]);\n// EnrichedMicrosoft365AuditLogs Query: Identify users who have been made owners of more than 'max_owner_count' teams\nlet high_owner_count_enriched = (\n EnrichedMicrosoft365AuditLogs\n | where Workload == \"MicrosoftTeams\"\n | where Operation == \"MemberRoleChanged\"\n | extend Member = tostring(UserId)\n | extend NewRole = toint(parse_json(tostring(AdditionalProperties)).Role)\n | where NewRole == 2 // Role 2 corresponds to \"Owner\"\n | summarize TeamCount = dcount(ObjectId) by Member\n | where TeamCount > max_owner_count\n | project Member\n);\n// EnrichedMicrosoft365AuditLogs Query: Fetch details for users with high ownership count\nlet EnrichedEvents = EnrichedMicrosoft365AuditLogs\n | where Workload == \"MicrosoftTeams\"\n | where Operation == \"MemberRoleChanged\"\n | extend Member = tostring(UserId)\n | extend NewRole = toint(parse_json(tostring(AdditionalProperties)).Role)\n | where NewRole == 2 // Role 2 corresponds to \"Owner\"\n | where Member in (high_owner_count_enriched)\n | extend AccountName = tostring(split(Member, \"@\")[0]), AccountUPNSuffix = tostring(split(Member, \"@\")[1]);\n// Combine Office and Enriched Logs\nlet CombinedEvents = OfficeEvents\n | union EnrichedEvents\n | summarize by Member, AccountName, AccountUPNSuffix;\n// Final Output\nCombinedEvents\n| order by Member asc\n| project Member, AccountName, AccountUPNSuffix\n",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"PrivilegeEscalation"
],
"techniques": [
"T1078"
],
"templateVersion": "2.0.2"
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}