Home / AWS

AWSRunbookAdvanced

Sev1: compromised EC2 instance (crypto-mining, malware, GuardDuty alert) — isolate and preserve evidence

Contain a compromised EC2 instance without destroying evidence. Isolate with a forensic security group, detach from Auto Scaling and load balancers, revoke the instance role's credentials, snapshot volumes and decide when to rebuild.

Deepak Bhardwaj3 min read

Applies toAmazon EC2, Amazon GuardDuty, AWS Systems Manager, Amazon EBS, AWS CLI v2

Signals

  • GuardDuty findings like CryptoCurrency:EC2/BitcoinTool.B!DNS, Backdoor:EC2/C&CActivity.B, UnauthorizedAccess:EC2/SSHBruteForce (outbound), or InstanceCredentialExfiltration.
  • CPU pinned at 100% with no matching traffic; unknown processes; outbound traffic to odd ports.

Rules of engagement

  • Don't terminate first. You lose the evidence and the chance to learn how they got in.
  • Don't log in and poke around with your admin account if you can avoid it — capture first.
  • Tell your security team; follow their process if one exists.

1. Protect the instance from termination and scaling

aws ec2 modify-instance-attribute --instance-id i-0bad123 --disable-api-termination
aws autoscaling detach-instances --instance-ids i-0bad123 \
  --auto-scaling-group-name asg-web --no-should-decrement-desired-capacity
aws elbv2 deregister-targets --target-group-arn <tg-arn> --targets Id=i-0bad123

The ASG launches a clean replacement, so service continues.

2. Isolate the network

Create a security group with no inbound and no outbound rules:

SG=$(aws ec2 create-security-group --group-name forensic-isolation --description "isolation" --vpc-id vpc-0123 --query GroupId --output text)
aws ec2 revoke-security-group-egress --group-id $SG --ip-permissions '[{"IpProtocol":"-1","IpRanges":[{"CidrIp":"0.0.0.0/0"}]}]'
aws ec2 modify-instance-attribute --instance-id i-0bad123 --groups $SG

Warning

Security groups are stateful: existing tracked connections may continue after you swap groups. Add a network ACL deny on the subnet (or move to an isolated subnet) to cut established sessions too.

3. Revoke the instance role's credentials

Credentials from the instance profile may already be stolen. Revoke sessions issued before now on the role (see the compromised keys runbook) and check CloudTrail for API calls by that role from IPs that are not the instance.

aws iam put-role-policy --role-name web-instance-role --policy-name AWSRevokeOlderSessions \
  --policy-document file://revoke-before-now.json

4. Capture evidence

aws ec2 describe-instances --instance-ids i-0bad123 > instance-metadata.json
for v in $(aws ec2 describe-instances --instance-ids i-0bad123 --query "Reservations[].Instances[].BlockDeviceMappings[].Ebs.VolumeId" --output text); do
  aws ec2 create-snapshot --volume-id $v --description "forensic i-0bad123 $(date -u +%FT%TZ)" \
    --tag-specifications 'ResourceType=snapshot,Tags=[{Key=case,Value=IR-2026-1024}]'
done

Memory capture (if your team does it) must happen before stopping — use a pre-approved tool via SSM Run Command. Copy GuardDuty findings, VPC Flow Logs and CloudTrail for the window.

5. Find the entry point

Common entry Check
Exposed SSH/RDP with weak credentials Security group history in AWS Config, auth logs
Vulnerable app (RCE) Web server logs, WAF logs
Leaked keys used to launch instances CloudTrail RunInstances caller
Malicious container image or package Image provenance, package lock files

6. Recover

Rebuild from a known-good AMI and IaC — never "clean" a compromised host. Patch the entry point first, rotate any secrets the instance could read, then release the isolated instance to security for analysis and later termination.

Prevent it next time

  • No public SSH/RDP; use Session Manager.
  • IMDSv2 required (HttpTokens=required) to reduce credential theft via SSRF.
  • GuardDuty with runtime monitoring, Inspector for vulnerabilities, findings to on-call.