Modify Cloud Compute Infrastructure
This detection identifies adversary attempts to modify cloud compute infrastructure components — including creating, deleting, or reverting virtual machines, snapshots, and compute configurations — to bypass access controls, evade detection, or erase forensic evidence. The KQL query monitors Azure Activity logs for anomalous compute operations such as snapshot creation from running instances, instance deletion outside approved maintenance windows, and configuration changes to security-relevant VM properties. The SPL query targets AWS CloudTrail events for equivalent actions across EC2, EBS, and related compute services. High-privilege cloud principals performing bulk or unusual compute operations are the primary focus, particularly when those operations originate from unfamiliar IP addresses or occur outside normal change windows.
What is T1578 Modify Cloud Compute Infrastructure?
Modify Cloud Compute Infrastructure (T1578) maps to the Defense Evasion tactic — the adversary is trying to avoid being detected in MITRE ATT&CK.
This page provides production-ready detection logic for Modify Cloud Compute Infrastructure, covering the data sources and telemetry it touches: Azure Monitor, Azure Activity Logs, Microsoft Sentinel. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Defense Evasion
- Canonical reference
- https://attack.mitre.org/techniques/T1578/
AzureActivity
| where TimeGenerated >= ago(1d)
| where ResourceProviderValue =~ "Microsoft.Compute"
| where OperationNameValue has_any (
"Microsoft.Compute/virtualMachines/write",
"Microsoft.Compute/virtualMachines/delete",
"Microsoft.Compute/snapshots/write",
"Microsoft.Compute/snapshots/delete",
"Microsoft.Compute/disks/write",
"Microsoft.Compute/disks/delete",
"Microsoft.Compute/virtualMachines/deallocate/action",
"Microsoft.Compute/virtualMachines/generalize/action",
"Microsoft.Compute/virtualMachines/capture/action",
"Microsoft.Compute/virtualMachines/extensions/write",
"Microsoft.Compute/virtualMachineScaleSets/write",
"Microsoft.Compute/virtualMachineScaleSets/delete",
"Microsoft.Compute/restorePointCollections/write"
)
| where ActivityStatusValue in~ ("Succeeded", "Started")
| extend CallerIp = tostring(CallerIpAddress)
| extend PrincipalName = tostring(Caller)
| extend OperationType = case(
OperationNameValue has "delete", "DELETE",
OperationNameValue has "/write", "CREATE_OR_MODIFY",
OperationNameValue has "capture", "CAPTURE",
OperationNameValue has "generalize", "GENERALIZE",
OperationNameValue has "deallocate", "DEALLOCATE",
OperationNameValue has "extension", "EXTENSION_CHANGE",
"OTHER"
)
| extend RiskScore = case(
OperationType == "DELETE", 3,
OperationType == "CAPTURE", 3,
OperationType == "GENERALIZE", 3,
OperationType == "EXTENSION_CHANGE", 2,
OperationType == "CREATE_OR_MODIFY", 1,
0
)
| summarize
OperationCount = count(),
UniqueResources = dcount(ResourceId),
OperationTypes = make_set(OperationType),
TotalRiskScore = sum(RiskScore),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
Resources = make_set(ResourceId, 10)
by PrincipalName, CallerIp, ResourceGroup, SubscriptionId
| where TotalRiskScore >= 3 or (OperationCount >= 5 and UniqueResources >= 3)
| extend AlertReason = case(
TotalRiskScore >= 6, "High-risk compute operations: multiple delete/capture/generalize actions",
TotalRiskScore >= 3 and OperationCount >= 5, "Elevated compute modification activity with destructive operations",
OperationCount >= 5 and UniqueResources >= 3, "Bulk modifications across multiple compute resources",
"Suspicious compute infrastructure modification"
)
| project
FirstSeen,
LastSeen,
PrincipalName,
CallerIp,
ResourceGroup,
SubscriptionId,
OperationCount,
UniqueResources,
OperationTypes,
TotalRiskScore,
AlertReason,
Resources
| sort by TotalRiskScore desc, OperationCount desc Monitors Azure Activity logs for anomalous compute infrastructure modifications by a single principal. Scores operations by risk (DELETE/CAPTURE/GENERALIZE=3pts, EXTENSION_CHANGE=2pts, CREATE/MODIFY=1pt) and alerts when cumulative risk score reaches 3 or bulk modifications occur across 3+ resources. Covers VM lifecycle operations, snapshot creation/deletion, disk manipulation, generalization, capture, extension changes, and scale set modifications.
Data Sources
Required Tables
False Positives
- Legitimate DevOps CI/CD pipelines creating and deleting ephemeral build VMs during automated deployment workflows
- Authorized disaster recovery tests involving snapshot creation, VM replication, and failover exercises
- Infrastructure-as-Code tooling (Terraform, Bicep, ARM templates) running bulk creates/deletes during planned maintenance windows
- Cloud cost optimization scripts automatically deallocating idle VMs on a schedule
- Security scanning tools or backup agents installing VM extensions across a fleet
Sigma rule & cross-platform mapping
The detection logic for Modify Cloud Compute Infrastructure (T1578) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
product: azure Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1578
References (9)
- https://attack.mitre.org/techniques/T1578/
- https://www.mandiant.com/resources/reports/m-trends-2020
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitor-with-cloudtrail.html
- https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/activity-log
- https://attack.mitre.org/techniques/T1578/001/
- https://attack.mitre.org/techniques/T1578/002/
- https://attack.mitre.org/techniques/T1578/003/
- https://attack.mitre.org/techniques/T1578/004/
- https://attack.mitre.org/techniques/T1578/005/
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1AWS - Create and Share EC2 Snapshot Cross-Account
Expected signal: AWS CloudTrail events: CreateSnapshot (ec2.amazonaws.com), ModifySnapshotAttribute with createVolumePermission add — both visible in CloudTrail within 5-15 minutes
- Test 2Azure - Create VM Snapshot and Capture VM Image
Expected signal: AzureActivity log entries: Microsoft.Compute/snapshots/write (Succeeded), Microsoft.Compute/virtualMachines/capture/action (Started/Succeeded) — visible in Azure Monitor within 2-5 minutes
- Test 3AWS - Terminate Running EC2 Instance (Evidence Destruction)
Expected signal: AWS CloudTrail events: RunInstances (ec2.amazonaws.com) followed by TerminateInstances — both visible within 5-15 minutes. Instance state change to 'shutting-down' then 'terminated' visible in EC2 describe-instances.
Response Playbook
Triage
- Step 1: Identify the principal (IAM user/role ARN for AWS, Azure AD object for Azure) responsible for the compute modifications. Check if this is a human identity or a service principal/managed identity.
- Step 2: Determine if the source IP address is expected for this principal. Cross-reference against known corporate IP ranges, VPN egress IPs, and the principal's historical login locations using CloudTrail/AzureActivity over the prior 30 days.
- Step 3: Review the specific operations performed. Prioritize investigation of DELETE, TERMINATE, EXPORT, and CAPTURE operations as these indicate potential evidence destruction or data staging. Note the sequence and timing of operations.
- Step 4: Check if the targeted resources were critical production systems. Query asset inventory or resource tags to determine environment (prod/staging/dev) and sensitivity classification.
- Step 5: Review the time window of the activity. Determine if operations occurred during business hours, approved change windows, or maintenance periods. Off-hours activity from human identities is elevated risk.
- Step 6: Check for concurrent suspicious activity by the same principal — API calls to IAM (privilege escalation), S3/Blob (data staging), or CloudTrail/Azure Monitor (log tampering) in the same session.
- Step 7: Look for any preceding authentication anomalies — MFA bypass, impossible travel, new device sign-in — in the 24 hours before the compute modification activity using SigninLogs or CloudTrail ConsoleLogin events.
- Step 8: Determine if any snapshots or images were created and then shared externally (ModifySnapshotAttribute with public or cross-account permissions in AWS; AzureActivity for snapshot access policy changes).
Containment
- Immediately revoke or disable the compromised principal's credentials: deactivate IAM access keys (AWS), revoke Azure AD session tokens, or disable the service principal.
- If an IAM role or managed identity is involved, remove or restrict the role's attached policies to prevent further compute modifications while investigation proceeds.
- For AWS: use AWS SCPs (Service Control Policies) to deny ec2:* actions for the affected account at the Organizations level if the blast radius is unclear.
- Place the affected virtual machines in an isolated network security group or VPC with no ingress/egress to prevent attacker re-entry while forensics are performed.
- Preserve any snapshots or images created by the suspect activity — do NOT delete them. Tag them as forensic evidence and restrict access to the security team only.
- If instances were terminated, immediately check if recovery is possible from existing snapshots or AMIs before proceeding. Capture the instance termination timestamp for log correlation.
- Enable enhanced logging (VPC Flow Logs, Azure NSG Flow Logs) on the affected subnets/VNets if not already active, to capture any lateral movement attempts.
Evidence Collection
- Export the full AzureActivity or CloudTrail log window for the affected principal, spanning 72 hours before the first suspicious operation through the present. Download as JSON for offline analysis.
- Collect the complete API call sequence for the session — for AWS use CloudTrail with RequestParameters and ResponseElements fields to reconstruct exactly what resources were created, modified, or deleted.
- For any created snapshots (AWS: CreateSnapshot, Azure: snapshots/write), document the source volume/disk ID, creation time, snapshot ID, and any sharing permissions applied afterward.
- Pull IAM/RBAC activity logs: AWS IAM events (GetSessionToken, AssumeRole, CreateAccessKey) and Azure role assignment changes in the 7 days preceding the compute modifications.
- Capture the current state of the affected compute resources: list running instances, attached volumes, existing snapshots, and any exported images. Compare against known-good inventory from CMDB or prior snapshots.
- Collect authentication logs for the compromised principal from identity providers (Azure AD sign-in logs, AWS IAM last used data, Okta/PingFederate SSO logs if applicable).
- Export any VM extension configurations (Azure) or EC2 user-data/instance metadata (AWS) that were modified, as attackers may have installed backdoors through extension or startup scripts.
- Preserve cloud provider billing records for the affected account — unusual compute spend may indicate cryptomining instances spun up alongside the defensive evasion activity.
Escalation Criteria
- ! Escalate immediately if snapshots were shared externally (cross-account or made public) — this indicates active data exfiltration in progress.
- ! Escalate if the compromised principal is a privileged service account (e.g., a CI/CD pipeline identity, backup service, or cloud admin role) as blast radius may extend across multiple workloads.
- ! Escalate if VM instances were deleted and no snapshots were taken beforehand — this is likely evidence destruction and indicates an advanced adversary covering tracks.
- ! Escalate if concurrent CloudTrail/Azure Monitor log tampering is detected (DeleteTrail, StopLogging, DiagnosticSettings delete) alongside compute modifications — attacker is actively blinding defenders.
- ! Escalate if the activity spans multiple AWS accounts or Azure subscriptions — cross-account compute modification indicates a broader compromise beyond a single account.
- ! Escalate if the activity is correlated with a known threat actor TTP pattern — e.g., creation of an instance followed by snapshot creation on a domain controller (DCSYNC staging) or database server.
Investigation Guide
Forensic Artifacts
- >
AWS CloudTrail event logs (S3 bucket or CloudWatch Logs): ec2.amazonaws.com events with full RequestParameters and ResponseElements - >
Azure Activity Log: Microsoft.Compute/* operations with Caller, CallerIpAddress, and HttpRequest fields - >
AWS EC2 instance metadata: /latest/meta-data/iam/security-credentials/ — may reveal if instance role was used to perform modifications - >
Cloud provider billing anomaly reports: unexpected compute spend indicating rogue instances - >
Snapshot and AMI registry: list all snapshots/images in the account and their sharing permissions (aws ec2 describe-snapshots --owner-ids self) - >
Azure resource lock logs: check if resource locks were removed prior to deletion to identify deliberate evidence destruction - >
VPC Flow Logs / Azure NSG Flow Logs: network traffic from created instances that may reveal C2 communication - >
AWS Config change history: resource configuration timeline for affected instances showing before/after state of all attribute changes - >
CloudTrail Data Events for S3: if attacker exported snapshots to S3 buckets before deletion
Tuning Guidance
Start by establishing a baseline of approved principals and time windows for compute operations. Whitelist known CI/CD service accounts (Terraform, Ansible controller nodes, Jenkins build agents) and backup service principals by ARN/object ID. Tune the RiskScore threshold upward (from 3 to 5) in environments with active blue/green deployment patterns. For AWS environments using Auto Scaling Groups, filter out events where the userIdentity.invokedBy field equals 'autoscaling.amazonaws.com' or 'spotfleet.amazonaws.com'. In Azure, suppress alerts where the Caller matches your DevOps service principal pattern and the OperationName is limited to 'write' (not delete/capture). Consider adding ResourceGroup-level allowlists for ephemeral sandbox environments where bulk creates and deletes are expected. Set up a separate high-sensitivity alert for any snapshot sharing (ModifySnapshotAttribute with public or cross-account permissions in AWS) without the scoring threshold — this action has almost no legitimate cross-account use case and warrants immediate investigation.
Hunting Queries
Hunts for bulk snapshot creation within short time windows — a strong indicator of adversarial data staging or exfiltration preparation. Three or more snapshots created within an hour by the same principal or in the same resource group is suspicious outside backup windows.
AzureActivity
| where TimeGenerated >= ago(7d)
| where ResourceProviderValue =~ "Microsoft.Compute"
| where OperationNameValue has "snapshots/write"
| where ActivityStatusValue =~ "Succeeded"
| extend SnapshotName = tostring(split(ResourceId, "/")[-1])
| extend SourceDisk = tostring(parse_json(tostring(parse_json(Properties).requestbody)).properties.creationData.sourceResourceId)
| summarize SnapshotCount = count(), Disks = make_set(SourceDisk), Principals = make_set(Caller)
by bin(TimeGenerated, 1h), ResourceGroup
| where SnapshotCount >= 3
| extend HuntNote = "Multiple snapshots created within 1-hour window — potential data staging for exfiltration" index=* sourcetype="aws:cloudtrail" eventName="CreateSnapshot" OR eventName="CopySnapshot"
| spath input=userIdentity output=principalArn path=arn
| spath input=requestParameters output=volumeId path=volumeId
| spath input=requestParameters output=description path=description
| eval hour = strftime(_time, "%Y-%m-%d %H:00:00")
| stats count as snapshots, values(volumeId) as volumes, values(awsRegion) as regions by principalArn, hour
| where snapshots >= 3
| eval huntNote = "Bulk snapshot creation: potential data staging — " . snapshots . " snapshots in 1 hour" Hunts for coordinated deletion of multiple compute resource types (VMs+snapshots+disks or instances+volumes+AMIs) within short windows. Simultaneous deletion across resource types suggests deliberate evidence destruction rather than routine deprovisioning.
AzureActivity
| where TimeGenerated >= ago(14d)
| where ResourceProviderValue =~ "Microsoft.Compute"
| where OperationNameValue has_any ("virtualMachines/delete", "snapshots/delete", "disks/delete")
| where ActivityStatusValue =~ "Succeeded"
| extend DeletedResource = tostring(split(ResourceId, "/")[-1])
| extend ResourceType = case(
ResourceId has "/virtualMachines/", "VM",
ResourceId has "/snapshots/", "Snapshot",
ResourceId has "/disks/", "Disk",
"Other"
)
| summarize
DeleteCount = count(),
ResourceTypes = make_set(ResourceType),
DeletedResources = make_set(DeletedResource, 20),
Callers = make_set(Caller)
by bin(TimeGenerated, 4h), ResourceGroup, SubscriptionId
| where DeleteCount >= 3 or (array_length(ResourceTypes) >= 2)
| extend HuntNote = "Multi-resource deletion pattern — possible evidence destruction or infrastructure teardown" index=* sourcetype="aws:cloudtrail"
(eventName="TerminateInstances" OR eventName="DeleteSnapshot" OR eventName="DeleteVolume" OR eventName="DeregisterImage")
| spath input=userIdentity output=principalArn path=arn
| eval resourceType = case(
eventName="TerminateInstances", "Instance",
eventName="DeleteSnapshot", "Snapshot",
eventName="DeleteVolume", "Volume",
eventName="DeregisterImage", "Image",
"Unknown"
)
| eval timeWindow = strftime(_time, "%Y-%m-%d %H")
| stats dc(resourceType) as uniqueResourceTypes, count as deleteOps, values(resourceType) as types, values(eventName) as events by principalArn, awsRegion, timeWindow
| where deleteOps >= 3 OR uniqueResourceTypes >= 2
| eval huntNote = "Coordinated deletion across " . uniqueResourceTypes . " resource types — potential evidence destruction" Hunts for suspicious VM extension installations from unknown publishers (Azure) and EC2 user-data modifications containing shell execution commands (AWS). These are stealthy persistence mechanisms that provide attacker code execution on modified instances without triggering typical process-based detections.
AzureActivity
| where TimeGenerated >= ago(7d)
| where ResourceProviderValue =~ "Microsoft.Compute"
| where OperationNameValue has_any ("virtualMachines/extensions/write", "virtualMachines/write")
| where ActivityStatusValue =~ "Succeeded"
| extend Props = parse_json(Properties)
| extend RequestBody = parse_json(tostring(Props.requestbody))
| extend ExtensionType = tostring(RequestBody.properties.type)
| extend ExtensionPublisher = tostring(RequestBody.properties.publisher)
| where isnotempty(ExtensionType)
| where not (ExtensionPublisher has_any ("Microsoft", "Qualys", "Trend", "CrowdStrike", "Carbon Black", "Datadog", "Dynatrace"))
| project TimeGenerated, Caller, CallerIpAddress, ResourceGroup, ExtensionType, ExtensionPublisher, ResourceId
| extend HuntNote = "Unknown/untrusted extension publisher — potential backdoor installation via VM extension" index=* sourcetype="aws:cloudtrail" eventName="ModifyInstanceAttribute"
| spath input=requestParameters output=attribute path=attribute
| spath input=requestParameters output=userData path=userData.value
| where attribute="userData" AND isnotnull(userData)
| spath input=userIdentity output=principalArn path=arn
| eval decodedData = urldecode(userData)
| regex decodedData="(curl|wget|bash|python|powershell|nc |ncat|/bin/sh|cmd\.exe|base64)"
| table _time, principalArn, sourceIPAddress, awsRegion, requestParameters, decodedData
| eval huntNote = "Instance user-data modified with suspicious shell commands — possible backdoor injection" Atomic Red Team Tests
Simulates adversary creating a snapshot of an EBS volume and sharing it with an external AWS account, representing data staging for exfiltration. Requires AWS CLI configured with ec2:CreateSnapshot and ec2:ModifySnapshotAttribute permissions.
Command
# Step 1: Get an existing volume ID to snapshot (use a test volume)
VOLUME_ID=$(aws ec2 describe-volumes --filters Name=status,Values=available --query 'Volumes[0].VolumeId' --output text --region us-east-1)
echo "Target volume: $VOLUME_ID"
# Step 2: Create snapshot (T1578.001 - Create Snapshot)
SNAPSHOT_ID=$(aws ec2 create-snapshot \
--volume-id $VOLUME_ID \
--description "atomic-test-t1578-$(date +%s)" \
--region us-east-1 \
--query 'SnapshotId' --output text)
echo "Created snapshot: $SNAPSHOT_ID"
# Step 3: Wait for snapshot completion
aws ec2 wait snapshot-completed --snapshot-ids $SNAPSHOT_ID --region us-east-1
# Step 4: Share snapshot with external account (simulated cross-account exfil)
# Replace 123456789012 with a test account ID - this is the key malicious action
aws ec2 modify-snapshot-attribute \
--snapshot-id $SNAPSHOT_ID \
--attribute createVolumePermission \
--operation-type add \
--user-ids 123456789012 \
--region us-east-1
echo "Snapshot $SNAPSHOT_ID shared cross-account - CloudTrail event generated" Cleanup
aws ec2 modify-snapshot-attribute --snapshot-id $SNAPSHOT_ID --attribute createVolumePermission --operation-type remove --user-ids 123456789012 --region us-east-1 && aws ec2 delete-snapshot --snapshot-id $SNAPSHOT_ID --region us-east-1 && echo "Cleanup complete" Expected Telemetry
AWS CloudTrail events: CreateSnapshot (ec2.amazonaws.com), ModifySnapshotAttribute with createVolumePermission add — both visible in CloudTrail within 5-15 minutes
Expected Detection
SPL query should alert on CreateSnapshot + ModifySnapshotAttribute from same principal; separate alert for cross-account snapshot sharing should fire immediately on the ModifySnapshotAttribute event
Simulates adversary creating a disk snapshot and then capturing a VM as a managed image (generalize + capture), which could be used to revert changes or exfiltrate data in VM form. Requires Azure CLI authenticated with Contributor role on a test resource group.
Command
# Set variables - use a non-production test VM
RG="atomic-test-rg"
VM_NAME="atomic-test-vm"
LOCATION="eastus"
SNAPSHOT_NAME="atomic-snap-$(date +%s)"
# Step 1: Get the OS disk ID of the test VM
DISK_ID=$(az vm show -g $RG -n $VM_NAME --query storageProfile.osDisk.managedDisk.id -o tsv)
echo "Source disk: $DISK_ID"
# Step 2: Create snapshot of OS disk (T1578.001)
az snapshot create \
--resource-group $RG \
--name $SNAPSHOT_NAME \
--source $DISK_ID \
--location $LOCATION
echo "Snapshot created: $SNAPSHOT_NAME"
# Step 3: Capture VM as image (T1578 - evidence preservation / exfil staging)
# This generates Microsoft.Compute/virtualMachines/capture/action in AzureActivity
az vm capture \
--resource-group $RG \
--name $VM_NAME \
--vhd-name-prefix "atomictest" \
--overwrite
echo "VM capture attempted - AzureActivity events generated" Cleanup
az snapshot delete --resource-group $RG --name $SNAPSHOT_NAME --yes && echo "Snapshot deleted. Note: VM generalize is destructive - use a dedicated test VM only" Expected Telemetry
AzureActivity log entries: Microsoft.Compute/snapshots/write (Succeeded), Microsoft.Compute/virtualMachines/capture/action (Started/Succeeded) — visible in Azure Monitor within 2-5 minutes
Expected Detection
KQL query should produce a RiskScore of 6+ (CAPTURE=3 + CREATE_OR_MODIFY=1 + snapshot write=1) triggering the alert threshold for the initiating principal
Simulates adversary terminating a running EC2 instance to destroy evidence of malicious activity. This represents T1578.003 (Delete Cloud Instance). Run only against a dedicated test instance that is safe to terminate.
Command
# SAFETY: Only run against a tagged test instance
# First, launch a dedicated test instance to terminate
INSTANCE_ID=$(aws ec2 run-instances \
--image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
--instance-type t3.micro \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Purpose,Value=atomic-test-t1578},{Key=SafeToTerminate,Value=true}]' \
--region us-east-1 \
--query 'Instances[0].InstanceId' --output text)
echo "Test instance launched: $INSTANCE_ID"
# Wait for instance to enter running state
aws ec2 wait instance-running --instance-ids $INSTANCE_ID --region us-east-1
echo "Instance running. Proceeding with termination (T1578.003)"
# Terminate the instance - the primary malicious action being tested
aws ec2 terminate-instances \
--instance-ids $INSTANCE_ID \
--region us-east-1
echo "TerminateInstances API call made - CloudTrail event generated for instance $INSTANCE_ID" Cleanup
aws ec2 wait instance-terminated --instance-ids $INSTANCE_ID --region us-east-1 && echo "Instance $INSTANCE_ID fully terminated. No further cleanup needed." Expected Telemetry
AWS CloudTrail events: RunInstances (ec2.amazonaws.com) followed by TerminateInstances — both visible within 5-15 minutes. Instance state change to 'shutting-down' then 'terminated' visible in EC2 describe-instances.
Expected Detection
SPL query should score TerminateInstances at 3 risk points and RunInstances at 1 point (total: 4), meeting the alert threshold. Alert should identify the test principal's ARN and the us-east-1 region.