↳ GitHub sourceAnalytics ruleHigh

GCP Audit Logs - Detect Bulk VM Snapshot Deletion

Description

'Detects bulk deletion of Google Cloud VM snapshots within a short time period, which may indicate data destruction or defense evasion activities. VM snapshots are critical for backup and disaster recovery. Bulk deletion of snapshots can prevent recovery from incidents and may indicate malicious activity such as ransomware, data destruction, or an attempt to cover tracks after a security breach. Adversaries may delete snapshots to maximize damage, prevent forensic investigation, or hinder recovery efforts. This rule triggers when multiple snapshots are deleted by the same user within a 1-minute window.'
Rule type
Scheduled
Version
1.0.0
Declared status
Available
Query frequency
15m
Query period
15m
Trigger
gt 0

Declared MITRE coverage

Declared sources

Metadata from the source file. No dependencies inferred from KQL.

Connectors

Data types

KQL query

Original query, unchanged.

// Update these thresholds if noisy in your environment
let SnapshotDeletionThreshold = 10;
let TimeWindow = 1m;
GCPAuditLogs
| where ServiceName == "compute.googleapis.com"
| where MethodName has "compute.snapshots.delete"
| where GCPResourceType == "gce_snapshot" and Severity == "NOTICE"
| extend 
    AuthzInfoJson = parse_json(AuthorizationInfo),
    RequestMetadataJson = parse_json(RequestMetadata),
    ResponseJson = parse_json(Response)
| extend PermissionType = tostring(AuthzInfoJson[0].permissionType)
| where PermissionType == "ADMIN_WRITE"
| extend 
    CallerIpAddress = tostring(RequestMetadataJson.callerIp),
    UserAgent = tostring(RequestMetadataJson.callerSuppliedUserAgent),
    SnapshotName = extract(@"snapshots/([^/]+)", 1, GCPResourceName),
    OperationType = tostring(ResponseJson.operationType),
    OperationId = tostring(ResponseJson.id)
| summarize 
    SnapshotCount = count(),
    SnapshotList = make_set(SnapshotName, 100),
    FirstDeletion = min(TimeGenerated),
    LastDeletion = max(TimeGenerated),
    OperationIds = make_set(OperationId, 100),
    CallerIPs = make_set(CallerIpAddress, 10)
    by PrincipalEmail, ProjectId, UserAgent
| where SnapshotCount >= SnapshotDeletionThreshold
| extend DeletionTimeSpan = LastDeletion - FirstDeletion
| where DeletionTimeSpan <= TimeWindow
| extend 
    AccountName = tostring(split(PrincipalEmail, "@")[0]), 
    AccountUPNSuffix = tostring(split(PrincipalEmail, "@")[1])
| project 
    TimeGenerated = FirstDeletion,
    PrincipalEmail,
    ProjectId,
    SnapshotCount,
    SnapshotList,
    FirstDeletion,
    LastDeletion,
    DeletionTimeSpan,
    CallerIPs,
    UserAgent,
    OperationIds,
    AccountName,
    AccountUPNSuffix

Declared entities

AccountCloudApplication

Related content

Links established from declared identifiers and solution manifests.

Source provenance

GitHub

Displayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.

Source identifier
dfdffdc7-929f-4c7e-8f48-30e5ffddb067
Additional source files 2Solutions/Google Cloud Platform Audit Logs/Analytic Rules/GCPBulkVMSnapshotDeletion.yamlsource ↗Solutions/Google Cloud Platform Audit Logs/Data/Solution_GCPAuditLogs.jsonsolution-membership ↗
GSTEP / CATALOG TRACKING

Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC

GSTEP sync dates, separate from the source content’s publication dates.