Azure Automation Account Created


Description

Detects when an Azure Automation account is created. Azure Automation accounts can be used to automate management tasks and orchestrate actions across systems. Adversaries may create Automation accounts to maintain persistence in their target's environment by leveraging managed identities and runbooks to execute code with elevated privileges.

Query · python

from panther_azureactivity_helpers import (
    azure_activity_alert_context,
    azure_activity_success,
    extract_resource_name_from_id,
)

AUTOMATION_ACCOUNT_WRITE = "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WRITE"


def rule(event):
    return event.get(
        "operationName", ""
    ).upper() == AUTOMATION_ACCOUNT_WRITE and azure_activity_success(event)


def title(event):
    resource_id = event.get("resourceId", "<UNKNOWN_RESOURCE>")

    account_name = extract_resource_name_from_id(
        resource_id, "automationAccounts", default="<UNKNOWN_ACCOUNT>"
    )

    return f"Azure Automation Account Created: [{account_name}]"


def alert_context(event):
    context = azure_activity_alert_context(event)

    resource_id = event.get("resourceId", "")
    account_name = extract_resource_name_from_id(resource_id, "automationAccounts", default="")
    if account_name:
        context["automation_account_name"] = account_name

    return context

Analyst notes

  1. Query Azure Monitor Activity logs for all automation-related operations (runbook creation, webhook creation, job executions) for the newly created automation account in the 6 hours after the account was created
  2. Find all automation account creations by the callerIpAddress in the past 24 hours to identify if multiple accounts are being created
  3. Check if the callerIpAddress has created automation accounts in the past 90 days to establish if this is typical infrastructure deployment behavior
Raw source Azure Automation Account Created · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: azure_automation_account_created.py
RuleID: "Azure.MonitorActivity.Automation.AccountCreated"
DisplayName: "Azure Automation Account Created"
Enabled: true
LogTypes:
  - Azure.MonitorActivity
Severity: Info
Description: >
  Detects when an Azure Automation account is created. Azure Automation accounts can be used to
  automate management tasks and orchestrate actions across systems. Adversaries may create
  Automation accounts to maintain persistence in their target's environment by leveraging managed
  identities and runbooks to execute code with elevated privileges.
Reports:
  MITRE ATT&CK:
    - TA0003:T1078 # Persistence: Valid Accounts
    - TA0005:T1078 # Defense Evasion: Valid Accounts
Tags:
  - Persistence
  - Defense Evasion
  - Valid Accounts
Runbook: |
  1. Query Azure Monitor Activity logs for all automation-related operations (runbook creation, webhook creation, job executions) for the newly created automation account in the 6 hours after the account was created
  2. Find all automation account creations by the callerIpAddress in the past 24 hours to identify if multiple accounts are being created
  3. Check if the callerIpAddress has created automation accounts in the past 90 days to establish if this is typical infrastructure deployment behavior
Reference: https://github.com/elastic/detection-rules/blob/main/rules/integrations/azure/persistence_automation_account_created.toml
SummaryAttributes:
  - resourceId
  - callerIpAddress
  - correlationId
Tests:
  - Name: Automation Account Created Successfully
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-22T10:30:00.0000000Z",
        "resourceId": "/subscriptions/12345678-1234-1234-1234-123456789abc/resourceGroups/automation-rg/providers/Microsoft.Automation/automationAccounts/malicious-automation",
        "operationName": "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/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: Automation Account Created Case Insensitive
    ExpectedResult: true
    Log:
      {
        "time": "2025-12-22T11:15:00.0000000Z",
        "resourceId": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/prod-automation/providers/Microsoft.Automation/automationAccounts/prod-automation-account",
        "operationName": "microsoft.automation/automationaccounts/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: Different Operation
    ExpectedResult: false
    Log:
      {
        "time": "2025-12-22T13:00:00.0000000Z",
        "resourceId": "/subscriptions/44444444-4444-4444-4444-444444444444/resourceGroups/automation-rg/providers/Microsoft.Automation/automationAccounts/existing-account",
        "operationName": "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/DELETE",
        "category": "Administrative",
        "resultType": "Success",
        "callerIpAddress": "4.4.4.4",
        "correlationId": "d4e5f6a7-b8c9-0123-def0-456789012345",
        "tenantId": "44444444-4444-4444-4444-444444444444"
      }

# ------ paired body: azure_automation_account_created.py ------

from panther_azureactivity_helpers import (
    azure_activity_alert_context,
    azure_activity_success,
    extract_resource_name_from_id,
)

AUTOMATION_ACCOUNT_WRITE = "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WRITE"


def rule(event):
    return event.get(
        "operationName", ""
    ).upper() == AUTOMATION_ACCOUNT_WRITE and azure_activity_success(event)


def title(event):
    resource_id = event.get("resourceId", "<UNKNOWN_RESOURCE>")

    account_name = extract_resource_name_from_id(
        resource_id, "automationAccounts", default="<UNKNOWN_ACCOUNT>"
    )

    return f"Azure Automation Account Created: [{account_name}]"


def alert_context(event):
    context = azure_activity_alert_context(event)

    resource_id = event.get("resourceId", "")
    account_name = extract_resource_name_from_id(resource_id, "automationAccounts", default="")
    if account_name:
        context["automation_account_name"] = account_name

    return context

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.