Detection rules › Kusto

Vaikora - Engine offline

Status
available
Severity
medium
Time window
1d
Group by
TenantId_s
Source
github.com/Azure/Azure-Sentinel

Identifies a Vaikora for O365 engine outage by absent quarantine telemetry. Fires when a tenant active in the last 24 hours has sent no rows in the last two hours, indicating the customer VM is unhealthy or the Graph subscription has lapsed.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Rule body

id: 968b70c1-b468-418a-ac02-1eb74783a52a
name: Vaikora - Engine offline
description: |
  Identifies a Vaikora for O365 engine outage by absent quarantine telemetry. Fires when a tenant active in the last 24 hours has sent no rows in the last two hours, indicating the customer VM is unhealthy or the Graph subscription has lapsed.
severity: Medium
requiredDataConnectors:
  - connectorId: VaikoraO365
    dataTypes:
      - VaikoraO365_Quarantine_CL
queryFrequency: 30m
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1562
query: |
  let recentTenants = toscalar(
    VaikoraO365_Quarantine_CL
    | where TimeGenerated >= ago(2h)
    | summarize make_set(TenantId_s)
  );
  VaikoraO365_Quarantine_CL
  | where TimeGenerated between (ago(1d) .. ago(2h))
  | summarize LastSeen = max(TimeGenerated) by TenantId_s
  | where TenantId_s !in (recentTenants)
  | project TimeGenerated = now(), TenantId = TenantId_s, LastSeen, HoursOffline = (now() - LastSeen) / 1h
entityMappings:
  - entityType: CloudApplication
    fieldMappings:
      - identifier: Name
        columnName: TenantId
alertDetailsOverride:
  alertDisplayNameFormat: "Vaikora-O365 engine offline for tenant {{TenantId}}"
  alertDescriptionFormat: "No Vaikora-O365 quarantine telemetry has arrived from this tenant in the last 2 hours. Last seen: {{LastSeen}}."
version: 1.0.0
kind: Scheduled

Stages and Predicates

Let binding: recentTenants used in Stage 4

let recentTenants = toscalar(
  VaikoraO365_Quarantine_CL
  | where TimeGenerated >= ago(2h)
  | summarize make_set(TenantId_s)
);

Stage 1: source

VaikoraO365_Quarantine_CL

Stage 2: where

| where TimeGenerated between (ago(1d) .. ago(2h))

Stage 3: summarize

| summarize LastSeen = max(TimeGenerated) by TenantId_s

Stage 4: where

| where TenantId_s !in (recentTenants)

Stage 5: project

| project TimeGenerated = now(), TenantId = TenantId_s, LastSeen, HoursOffline = (now() - LastSeen) / 1h

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
TenantId_seqrecentTenantsexcludes:TenantId_s field:"TenantId_s" value:"recentTenants"

Output fields

These fields are emitted when the rule matches.

FieldSource
HoursOfflineproject
LastSeenproject
TenantIdproject
TimeGeneratedproject