Detection rules › Kusto

Multiple Teams deleted by a single user

Status
available
Severity
low
Time window
1d
Group by
UserId
Source
github.com/Azure/Azure-Sentinel

This detection flags the occurrences of deleting multiple teams within an hour. This data is a part of Office 365 Connector in Microsoft Sentinel.

MITRE ATT&CK coverage

Event coverage

Rule body kusto

id: 173f8699-6af5-484a-8b06-8c47ba89b380
name: Multiple Teams deleted by a single user
description: |
  'This detection flags the occurrences of deleting multiple teams within an hour.
  This data is a part of Office 365 Connector in Microsoft Sentinel.'
severity: Low
status: Available
requiredDataConnectors:
  - connectorId: Office365
    dataTypes:
      - OfficeActivity (Teams)
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Impact
relevantTechniques:
  - T1485
  - T1489
query: |
  // Adjust this value to change how many Teams should be deleted before including
  let max_delete_count = 3;
  // Adjust this value to change the timewindow the query runs over
    OfficeActivity
  | where OfficeWorkload =~ "MicrosoftTeams"
  | where Operation =~ "TeamDeleted"
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), DeletedTeams = make_set(TeamName, 1000) by UserId
  | where array_length(DeletedTeams) > max_delete_count
  | extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: UserId
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
version: 2.0.4
kind: Scheduled

Stages and Predicates

Parameters

let max_delete_count = 3;

Stage 1: source

OfficeActivity

Stage 2: where

| where OfficeWorkload =~ "MicrosoftTeams"

Stage 3: where

| where Operation =~ "TeamDeleted"

Stage 4: summarize

| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), DeletedTeams = make_set(TeamName, 1000) by UserId
Threshold
gt 3

Stage 5: where

| where array_length(DeletedTeams) > max_delete_count

Stage 6: extend

| extend AccountName = tostring(split(UserId, "@")[0]), AccountUPNSuffix = tostring(split(UserId, "@")[1])

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
DeletedTeamsgt
  • 3 transforms: array_length
OfficeWorkloadeq
  • MicrosoftTeams
Operationeq
  • TeamDeleted

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
DeletedTeamssummarize
EndTimesummarize
StartTimesummarize
UserIdsummarize
AccountNameextend
AccountUPNSuffixextend