Detection rules › Panther
Azure Automation Schedule Created or Modified
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
| Tactic | Techniques |
|---|---|
| Persistence | T1053.005 Scheduled Task/Job: Scheduled Task |
| Privilege Escalation | T1053.005 Scheduled Task/Job: Scheduled Task, T1068 Exploitation for Privilege Escalation |
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.
| Field | Kind | Values |
|---|---|---|
operationName | in |
|
resultType | in |
|
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 |