Detection rules › Panther

Azure Automation Schedule Created or Modified

Severity
informational
Log types
Azure.MonitorActivity
Tags
AZT505, Persistence, Privilege Escalation, Scheduled Task, Exploitation for Privilege Escalation
Reference
https://microsoft.github.io/Azure-Threat-Research-Matrix/Persistence/AZT505/AZT505-1
Source
github.com/panther-labs/panther-analysis

Detects when an Azure Automation schedule is created or modified. Schedules define when and how often automation runbooks execute. Adversaries may create or modify schedules to establish persistence by executing malicious runbooks at regular intervals or specific times. This technique allows attackers to maintain access and execute commands without requiring direct interaction.

MITRE ATT&CK coverage

Rule body yaml

AnalysisType: rule
Filename: azure_automation_schedule_created.py
RuleID: "Azure.MonitorActivity.Automation.ScheduleCreated"
DisplayName: "Azure Automation Schedule Created or Modified"
Enabled: true
LogTypes:
  - Azure.MonitorActivity
Severity: Info
Description: >
  Detects when an Azure Automation schedule is created or modified. Schedules define when and how often
  automation runbooks execute. Adversaries may create or modify schedules to establish persistence by
  executing malicious runbooks at regular intervals or specific times. This technique allows attackers
  to maintain access and execute commands without requiring direct interaction.
Reports:
  MITRE ATT&CK:
    - TA0003:T1053.005 # Persistence: Scheduled Task/Job - Scheduled Task
    - TA0004:T1068 # Privilege Escalation: Exploitation for Privilege Escalation
Tags:
  - AZT505
  - Persistence
  - Privilege Escalation
  - Scheduled Task
  - Exploitation for Privilege Escalation
Runbook: |
  1. Find all automation account operations by the callerIpAddress in the 24 hours before and after this alert to identify if runbooks were created or modified alongside this schedule
  2. Query for runbook job execution events from the automation account in the 6 hours after the schedule creation to determine if the schedule has already triggered
  3. Check if the callerIpAddress is associated with known cloud providers, VPNs, or corporate network ranges used by authorized DevOps personnel
Reference: https://microsoft.github.io/Azure-Threat-Research-Matrix/Persistence/AZT505/AZT505-1
SummaryAttributes:
  - resourceId
  - callerIpAddress
  - correlationId
Tests:
  - Name: Schedule Created Successfully
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-23T10:30:00.0000000Z",
        "resourceId": "/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/automation-rg/providers/Microsoft.Automation/automationAccounts/MyAutomationAccount/schedules/DailyMaintenanceSchedule",
        "operationName": "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/SCHEDULES/WRITE",
        "operationVersion": "2021-06-22",
        "category": "Administrative",
        "resultType": "Success",
        "resultSignature": "200",
        "callerIpAddress": "1.1.1.1",
        "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "level": "Informational",
        "location": "eastus",
        "tenantId": "87654321-4321-4321-4321-111111111111"
      }
  - Name: Schedule Modified
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-23T11:15:00.0000000Z",
        "resourceId": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/prod-automation/providers/Microsoft.Automation/automationAccounts/ProdAccount/schedules/HourlyBackup",
        "operationName": "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/SCHEDULES/WRITE",
        "category": "Administrative",
        "resultType": "Succeeded",
        "callerIpAddress": "2.2.2.2",
        "correlationId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
        "level": "Information",
        "location": "westeurope",
        "tenantId": "22222222-2222-2222-2222-222222222222"
      }
  - Name: Persistence Schedule Created
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-23T12:00:00.0000000Z",
        "resourceId": "/subscriptions/33333333-3333-3333-3333-333333333333/resourceGroups/compromised-rg/providers/Microsoft.Automation/automationAccounts/CompromisedAccount/schedules/MaliciousSchedule",
        "operationName": "microsoft.automation/automationaccounts/schedules/write",
        "category": "Administrative",
        "resultType": "Success",
        "callerIpAddress": "3.3.3.3",
        "correlationId": "c3d4e5f6-a7b8-9012-cdef-333333333333",
        "level": "Informational",
        "location": "centralus",
        "tenantId": "33333333-3333-3333-3333-333333333333"
      }
  - Name: Different Operation
    ExpectedResult: false
    Log:
      {
        "time": "2025-12-23T15:00:00.0000000Z",
        "resourceId": "/subscriptions/66666666-6666-6666-6666-666666666666/resourceGroups/automation-rg/providers/Microsoft.Automation/automationAccounts/MyAccount/schedules/OldSchedule",
        "operationName": "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/SCHEDULES/DELETE",
        "category": "Administrative",
        "resultType": "Success",
        "callerIpAddress": "6.6.6.6",
        "correlationId": "f6a7b8c9-d0e1-2345-f012-678901234567",
        "tenantId": "66666666-6666-6666-6666-666666666666"
      }

Detection logic

Condition

operationName in "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/SCHEDULES/WRITE"
resultType in ["Success", "Succeeded"]

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
operationNamein
  • MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/SCHEDULES/WRITE
resultTypein
  • Succeeded
  • Success

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.

Field
callerIpAddress