Detection rules › Kusto

NRT Creation of expensive computes in Azure

Status
available
Severity
medium
Source
github.com/Azure/Azure-Sentinel

Identifies the creation of large size or expensive VMs (with GPUs or with a large number of virtual CPUs) in Azure. An adversary may create new or update existing virtual machines to evade defenses or use them for cryptomining purposes. For Windows/Linux Vm Sizes, see https://docs.microsoft.com/azure/virtual-machines/windows/sizes Azure VM Naming Conventions, see https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions

MITRE ATT&CK coverage

TacticTechniques
Defense ImpairmentT1578 Modify Cloud Compute Infrastructure

Event coverage

Rule body kusto

id: 56fe0db0-6779-46fa-b3c5-006082a53064
name: NRT Creation of expensive computes in Azure
description: |
  'Identifies the creation of large size or expensive VMs (with GPUs or with a large number of virtual CPUs) in Azure.
  An adversary may create new or update existing virtual machines to evade defenses or use them for cryptomining purposes.
  For Windows/Linux Vm Sizes, see https://docs.microsoft.com/azure/virtual-machines/windows/sizes 
  Azure VM Naming Conventions, see https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions'
severity: Medium
status: Available 
requiredDataConnectors:
  - connectorId: AzureActivity
    dataTypes:
      - AzureActivity
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1578
query: |
  let tokens = dynamic(["416","208","192","128","120","96","80","72","64","48","44","40","nc12","nc24","nv24"]);
  let operationList = dynamic(["microsoft.compute/virtualmachines/write", "microsoft.resources/deployments/write"]);
  AzureActivity
  | where OperationNameValue in~ (operationList)
  | where ActivityStatusValue startswith "Accept"
  | where Properties has 'vmSize'
  | extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties
  | extend vmSize = tostring((parsed_property.hardwareProfile).vmSize)
  | mv-apply token=tokens to typeof(string) on (where vmSize contains token)
  | extend ComputerName = tostring((parsed_property.osProfile).computerName)
  | project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize
  | extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: Caller
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: ComputerName  
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: CallerIpAddress
version: 2.0.3
kind: NRT

Stages and Predicates

Parameters

let tokens = dynamic(["416","208","192","128","120","96","80","72","64","48","44","40","nc12","nc24","nv24"]);
let operationList = dynamic(["microsoft.compute/virtualmachines/write", "microsoft.resources/deployments/write"]);

Stage 1: source

AzureActivity

Stage 2: where

| where OperationNameValue in~ (operationList)

Stage 3: where

| where ActivityStatusValue startswith "Accept"

Stage 4: where

| where Properties has 'vmSize'

Stage 5: extend

| extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties

Stage 6: extend

| extend vmSize = tostring((parsed_property.hardwareProfile).vmSize)

Stage 7: kusto:mv-apply

| mv-apply token=tokens to typeof(string) on (where vmSize contains token)

Stage 8: extend

| extend ComputerName = tostring((parsed_property.osProfile).computerName)

Stage 9: project

| project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize

Stage 10: extend

| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])

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
ActivityStatusValuestarts_with
  • Accept
OperationNameValuein
  • microsoft.compute/virtualmachines/write
  • microsoft.resources/deployments/write
Propertiesmatch
  • vmSize transforms: term
vmSizecontains
  • token

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.

FieldSource
ActivityStatusValueproject
Callerproject
CallerIpAddressproject
ComputerNameproject
OperationNameValueproject
TimeGeneratedproject
vmSizeproject
Nameextend
UPNSuffixextend