Back
Id56cb646e-56a0-4f0e-8866-9bc1dd15da78
RulenamePower Automate - Unusual bulk deletion of flow resources
DescriptionIdentifies 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.
SeverityMedium
TacticsImpact
DefenseEvasion
TechniquesT1485
T0828
T1562
Required data connectorsPowerAutomate
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft%20Business%20Applications/Analytic%20Rules/Power%20Automate%20-%20Unusual%20bulk%20deletion%20of%20flow%20resources.yaml
Version3.2.0
Arm template56cb646e-56a0-4f0e-8866-9bc1dd15da78.json
Deploy To Azure
// 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
version: 3.2.0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft%20Business%20Applications/Analytic%20Rules/Power%20Automate%20-%20Unusual%20bulk%20deletion%20of%20flow%20resources.yaml
triggerThreshold: 0
requiredDataConnectors:
- dataTypes:
  - PowerAutomateActivity
  connectorId: PowerAutomate
tactics:
- Impact
- DefenseEvasion
customDetails:
  DeletedFlowCount: DeletedFlowCount
relevantTechniques:
- T1485
- T0828
- T1562
kind: Scheduled
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
entityMappings:
- fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: UPNSuffix
  entityType: Account
- fieldMappings:
  - identifier: AppId
    columnName: PowerAutomateAppId
  entityType: CloudApplication
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.
triggerOperator: gt
status: Available
queryFrequency: 1h
id: 56cb646e-56a0-4f0e-8866-9bc1dd15da78
name: Power Automate - Unusual bulk deletion of flow resources
severity: Medium
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
queryPeriod: 14d
eventGroupingSettings:
  aggregationKind: SingleAlert
{
  "$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/56cb646e-56a0-4f0e-8866-9bc1dd15da78')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/56cb646e-56a0-4f0e-8866-9bc1dd15da78')]",
      "properties": {
        "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"
        },
        "alertRuleTemplateName": "56cb646e-56a0-4f0e-8866-9bc1dd15da78",
        "customDetails": {
          "DeletedFlowCount": "DeletedFlowCount"
        },
        "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.",
        "displayName": "Power Automate - Unusual bulk deletion of flow resources",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "CloudApplication",
            "fieldMappings": [
              {
                "columnName": "PowerAutomateAppId",
                "identifier": "AppId"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "SingleAlert"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft%20Business%20Applications/Analytic%20Rules/Power%20Automate%20-%20Unusual%20bulk%20deletion%20of%20flow%20resources.yaml",
        "query": "// minThreshold: Minimum number of apps to be deleted to be considered an anomaly;\n// This is to prevent one-off isolated delete flow to be considered outlier.\n// The Min Threshold can be reduced or increased according to the traffic in the organization.\nlet minThreshold=10;\nlet interval = 1h;\nlet startTime = ago(14d);\nlet endTime = now();\nlet query_frequency = 1h;\nlet flow_deletion_events = PowerAutomateActivity\n    | where TimeGenerated >= startTime\n    | where EventOriginalType =~ \"DeleteFlow\"\n    | extend IngestionTimeGenerated = TimeGenerated;\nflow_deletion_events\n| make-series DeletedFlowCount=count() on IngestionTimeGenerated from startTime to endTime step interval by ActorName, UserUpn, ActorUserId\n| extend(Anomalies, AnomalyScore, ExpectedUsage) = series_decompose_anomalies(DeletedFlowCount)\n| mv-expand\n    DeletedFlowCount to typeof(double),\n    IngestionTimeGenerated to typeof(datetime),\n    Anomalies to typeof(double),\n    AnomalyScore to typeof(double),\n    ExpectedUsage to typeof(long)\n| where IngestionTimeGenerated >= ago(query_frequency)\n| where Anomalies != 0 and DeletedFlowCount >= minThreshold\n| lookup (flow_deletion_events\n    | where IngestionTimeGenerated >= ago(query_frequency))\n    on ActorName, UserUpn, ActorUserId\n| extend\n    AccountName = tostring(split(ActorName, \"@\")[0]),\n    UPNSuffix = tostring(split(ActorName, \"@\")[1]),\n    PowerAutomateAppId = 27592\n| project\n    TimeGenerated,\n    ActorName,\n    DeletedFlowCount,\n    ExpectedUsage,\n    Anomalies,\n    AnomalyScore,\n    AccountName,\n    UPNSuffix,\n    PowerAutomateAppId,\n    UserUpn,\n    ActorUserId\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion",
          "Impact"
        ],
        "techniques": [
          "T1485",
          "T1562"
        ],
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}