Power Automate - Unusual bulk deletion of flow resources
| Id | 56cb646e-56a0-4f0e-8866-9bc1dd15da78 |
| Rulename | Power Automate - Unusual bulk deletion of flow resources |
| Description | Identifies bulk deletion of Power Automate flows that exceed a predefined threshold defined in the query and deviate from activity patterns observed in the last 14 days. |
| Severity | Medium |
| Tactics | Impact DefenseEvasion |
| Techniques | T1485 T0828 T1562 |
| Required data connectors | PowerAutomate |
| Kind | Scheduled |
| Query frequency | 1h |
| Query period | 14d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Power Automate - Unusual bulk deletion of flow resources.yaml |
| Version | 3.2.0 |
| Arm template | 56cb646e-56a0-4f0e-8866-9bc1dd15da78.json |
// minThreshold: Minimum number of apps to be deleted to be considered an anomaly;
// This is to prevent one-off isolated delete flow to be considered outlier.
// The Min Threshold can be reduced or increased according to the traffic in the organization.
let minThreshold=10;
let interval = 1h;
let startTime = ago(14d);
let endTime = now();
let query_frequency = 1h;
let flow_deletion_events = PowerAutomateActivity
| where TimeGenerated >= startTime
| where EventOriginalType =~ "DeleteFlow"
| extend IngestionTimeGenerated = TimeGenerated;
flow_deletion_events
| make-series DeletedFlowCount=count() on IngestionTimeGenerated from startTime to endTime step interval by ActorName, UserUpn, ActorUserId
| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(DeletedFlowCount)
| mv-expand
DeletedFlowCount to typeof(double),
IngestionTimeGenerated to typeof(datetime),
Anomalies to typeof(double),
AnomalyScore to typeof(double),
ExpectedUsage to typeof(long)
| where IngestionTimeGenerated >= ago(query_frequency)
| where Anomalies != 0 and DeletedFlowCount >= minThreshold
| lookup (flow_deletion_events
| where IngestionTimeGenerated >= ago(query_frequency))
on ActorName, UserUpn, ActorUserId
| extend
AccountName = tostring(split(ActorName, "@")[0]),
UPNSuffix = tostring(split(ActorName, "@")[1]),
PowerAutomateAppId = 27592
| project
TimeGenerated,
ActorName,
DeletedFlowCount,
ExpectedUsage,
Anomalies,
AnomalyScore,
AccountName,
UPNSuffix,
PowerAutomateAppId,
UserUpn,
ActorUserId
alertDetailsOverride:
alertDescriptionFormat: User {{ActorName}} deleted {{DeletedFlowCount}} flows in the last hour, surpassing the bulk delete threshold. This is anomalous compared to the past 14 days.
alertDisplayNameFormat: Power Automate - unusual bulk deletion of {{DeletedFlowCount}} flows
description: Identifies bulk deletion of Power Automate flows that exceed a predefined threshold defined in the query and deviate from activity patterns observed in the last 14 days.
kind: Scheduled
tactics:
- Impact
- DefenseEvasion
requiredDataConnectors:
- connectorId: PowerAutomate
dataTypes:
- PowerAutomateActivity
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Power Automate - Unusual bulk deletion of flow resources.yaml
severity: Medium
name: Power Automate - Unusual bulk deletion of flow resources
customDetails:
DeletedFlowCount: DeletedFlowCount
triggerThreshold: 0
queryPeriod: 14d
query: |
// minThreshold: Minimum number of apps to be deleted to be considered an anomaly;
// This is to prevent one-off isolated delete flow to be considered outlier.
// The Min Threshold can be reduced or increased according to the traffic in the organization.
let minThreshold=10;
let interval = 1h;
let startTime = ago(14d);
let endTime = now();
let query_frequency = 1h;
let flow_deletion_events = PowerAutomateActivity
| where TimeGenerated >= startTime
| where EventOriginalType =~ "DeleteFlow"
| extend IngestionTimeGenerated = TimeGenerated;
flow_deletion_events
| make-series DeletedFlowCount=count() on IngestionTimeGenerated from startTime to endTime step interval by ActorName, UserUpn, ActorUserId
| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(DeletedFlowCount)
| mv-expand
DeletedFlowCount to typeof(double),
IngestionTimeGenerated to typeof(datetime),
Anomalies to typeof(double),
AnomalyScore to typeof(double),
ExpectedUsage to typeof(long)
| where IngestionTimeGenerated >= ago(query_frequency)
| where Anomalies != 0 and DeletedFlowCount >= minThreshold
| lookup (flow_deletion_events
| where IngestionTimeGenerated >= ago(query_frequency))
on ActorName, UserUpn, ActorUserId
| extend
AccountName = tostring(split(ActorName, "@")[0]),
UPNSuffix = tostring(split(ActorName, "@")[1]),
PowerAutomateAppId = 27592
| project
TimeGenerated,
ActorName,
DeletedFlowCount,
ExpectedUsage,
Anomalies,
AnomalyScore,
AccountName,
UPNSuffix,
PowerAutomateAppId,
UserUpn,
ActorUserId
relevantTechniques:
- T1485
- T0828
- T1562
id: 56cb646e-56a0-4f0e-8866-9bc1dd15da78
queryFrequency: 1h
status: Available
version: 3.2.0
triggerOperator: gt
eventGroupingSettings:
aggregationKind: SingleAlert
entityMappings:
- entityType: Account
fieldMappings:
- columnName: AccountName
identifier: Name
- columnName: UPNSuffix
identifier: UPNSuffix
- entityType: CloudApplication
fieldMappings:
- columnName: PowerAutomateAppId
identifier: AppId