Detection rules › Kusto
NRT Creation of expensive computes in Azure
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
| Tactic | Techniques |
|---|---|
| Defense Impairment | T1578 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.
| Field | Kind | Values |
|---|---|---|
ActivityStatusValue | starts_with |
|
OperationNameValue | in |
|
Properties | match |
|
vmSize | contains |
|
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 | Source |
|---|---|
ActivityStatusValue | project |
Caller | project |
CallerIpAddress | project |
ComputerName | project |
OperationNameValue | project |
TimeGenerated | project |
vmSize | project |
Name | extend |
UPNSuffix | extend |