HIGHMalware20-40 min containment16 steps across 5 phases

    EC2 Crypto Mining

    An attacker has launched or hijacked EC2 instances to mine cryptocurrency. Common indicators: unexpected cost spikes, high CPU utilization on instances you did not launch, and GuardDuty alerts for cryptocurrency-related activity. Often follows credential compromise.

    Phase 1: Detection

    $ tail -f /var/log/cloudtrail/events.log
    1

    Check GuardDuty for crypto mining findings

    GuardDuty specifically detects EC2 instances communicating with known cryptocurrency mining pools.

    GuardDuty:CryptoCurrency:EC2/BitcoinTool.BCryptoCurrency:EC2/BitcoinTool.B!DNSUnauthorizedAccess:EC2/TorRelay
    2

    Identify suspicious EC2 instances

    List all running instances and look for ones you did not launch, especially large compute-optimized types.

    aws ec2 describe-instances \
      --filters "Name=instance-state-name,Values=running" \
      --query 'Reservations[].Instances[].{ID:InstanceId,Type:InstanceType,LaunchTime:LaunchTime,KeyName:KeyName}' \
      --output table
    CloudTrail:RunInstancesStartInstances
    3

    Check CloudWatch for CPU anomalies

    Crypto mining drives sustained ~100% CPU utilization. Check CloudWatch metrics for unexpected spikes.

    aws cloudwatch get-metric-statistics \
      --namespace AWS/EC2 \
      --metric-name CPUUtilization \
      --dimensions Name=InstanceId,Value=<instance-id> \
      --start-time <24h-ago> --end-time <now> \
      --period 3600 --statistics Average
    4

    Check for unexpected costs in Cost Explorer

    Crypto miners often spin up many large instances across multiple regions.

    aws ce get-cost-and-usage \
      --time-period Start=<7d-ago>,End=<today> \
      --granularity DAILY \
      --metrics BlendedCost \
      --group-by Type=DIMENSION,Key=SERVICE

    Phase 2: Containment

    $ ./containment.sh --isolate --immediate
    1

    Isolate the mining instances with a restrictive security group

    Create a quarantine security group with no inbound or outbound rules, then assign it to the compromised instance. Do NOT terminate yet - preserve for forensics.

    # Create isolation security group
    aws ec2 create-security-group \
      --group-name "IR-Isolation" \
      --description "Incident Response - No traffic" \
      --vpc-id <vpc-id>
    # Remove the default allow-all outbound rule
    aws ec2 revoke-security-group-egress \
      --group-id <isolation-sg-id> \
      --ip-permissions '[{"IpProtocol":"-1","IpRanges":[{"CidrIp":"0.0.0.0/0"}]}]'
    # Apply to the compromised instance
    aws ec2 modify-instance-attribute \
      --instance-id <instance-id> \
      --groups <isolation-sg-id>

    A new security group has no inbound rules but has a default outbound allow-all rule. You MUST remove the outbound rule to fully quarantine the instance.

    2

    Stop mining instances in all regions

    Check ALL regions - attackers often launch instances in regions you do not normally use.

    # List instances in all regions
    for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
      echo "=== $region ==="
      aws ec2 describe-instances --region $region \
        --filters "Name=instance-state-name,Values=running" \
        --query 'Reservations[].Instances[].InstanceId' --output text
    done
    3

    Contain the compromised credentials

    If the mining was caused by stolen credentials, follow the Compromised IAM Keys playbook to deactivate keys and revoke sessions.

    Phase 3: Eradication

    $ ./eradicate.sh --purge --verify
    1

    Terminate all unauthorized instances

    After forensic snapshots, terminate all instances launched by the attacker.

    aws ec2 terminate-instances --instance-ids <instance-id-1> <instance-id-2>
    2

    Delete attacker-created resources

    Remove any key pairs, AMIs, snapshots, or EBS volumes the attacker created.

    # Find key pairs created during incident
    aws cloudtrail lookup-events \
      --lookup-attributes AttributeKey=EventName,AttributeValue=CreateKeyPair \
      --start-time <incident-start>
    CloudTrail:CreateKeyPairImportKeyPairCreateImageCreateSnapshot
    3

    Remove any attacker-created IAM entities

    Check for and remove IAM users, roles, or policies created by the attacker for persistence.

    Phase 4: Recovery

    $ ./recovery.sh --restore --validate
    1

    Request a refund from AWS Support

    AWS often provides credits for unauthorized charges resulting from credential compromise. Contact AWS Support with the incident details.

    Include the CloudTrail evidence showing unauthorized RunInstances calls, the instance IDs, and the total cost impact.

    2

    Set up billing alarms

    Create CloudWatch billing alarms to catch unexpected cost spikes early.

    aws cloudwatch put-metric-alarm \
      --alarm-name "BillingAlarm-$100" \
      --metric-name EstimatedCharges \
      --namespace AWS/Billing \
      --statistic Maximum \
      --period 21600 \
      --threshold 100 \
      --comparison-operator GreaterThanThreshold \
      --evaluation-periods 1 \
      --alarm-actions <sns-topic-arn> \
      --dimensions Name=Currency,Value=USD
    3

    Verify no mining activity remains

    Monitor GuardDuty and CloudWatch for 48 hours to confirm all mining activity has stopped.

    Phase 5: Lessons Learned

    $ cat POST_INCIDENT_REVIEW.md
    1

    Deploy SCPs to restrict regions and instance types

    Use SCPs to deny RunInstances in regions you do not use and restrict large instance types.

    2

    Enable EC2 Instance Connect or SSM for access

    Eliminate SSH key pairs in favor of short-lived session-based access.

    3

    Rotate all access keys and enable MFA

    Crypto mining is almost always the result of credential compromise. Address the root cause.

    crypto-miningec2cost-spikemalwareunauthorized-instances

    Need Help with Incident Response?

    When an incident strikes, every minute counts. We help AWS teams prepare, detect, and respond to security incidents with proven expertise.