Your AWS bill just spiked to $47,000. Or you spotted EC2 instances spinning up in regions you never use. Or an alert fired from GuardDuty about API calls originating from an IP in another country. Your stomach drops. Your AWS account is compromised.
This is not a hypothetical — AWS account compromises happen every single day. Exposed access keys on GitHub, phishing attacks that steal console passwords, misconfigured IAM policies used as pivot points — the attack vectors are endless. What separates businesses that recover cleanly from those that lose everything is speed and knowing exactly what to do in the first few minutes.
This guide is your complete AWS incident response playbook. Save it now. Because when it happens, you will not have time to search for answers.
Phase 1: The First 15 Minutes — Immediate Containment
The first 15 minutes are the most critical. Your only goal right now is to stop the bleeding. Do not worry about understanding what happened or cleaning up — just stop the attacker from doing more damage.
Step 1: Change Root Account Password Immediately
Go to the AWS Management Console and sign in as root. Navigate to My Account → Security credentials. Under "Sign-in credentials", click "Edit" next to Password and set a new, strong password (at least 20 characters, mixed case, numbers, and symbols). Do this from a clean device — not the machine you discovered the breach on.
If you cannot access the root account because the attacker has changed the password, contact AWS Support immediately via the AWS Support Center or call +1-800-255-2931 (US). AWS has an emergency account recovery process. You will need access to the email address registered on the account and may need to verify your identity.
Step 2: Disable All Suspicious IAM Users and Access Keys
Navigate to IAM → Users. Look for any users you do not recognize or that were recently created. For any suspicious user, immediately:
- Click the user, go to the "Security credentials" tab
- Delete all access keys (note the key IDs first for forensics)
- Remove the console password
- Revoke all active sessions under "Sign-in activity"
Deactivate suspicious keys first rather than deleting them immediately — you need the key IDs to trace activity in CloudTrail logs. Delete after capturing forensic data.
Step 3: Revoke All Active IAM Sessions
Go to IAM → Users → [each user] → Security credentials and click "Revoke all active sessions". This invalidates all existing temporary credentials and forces re-authentication. For any compromised IAM role, attach a deny-all inline policy immediately:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}
Step 4: Enable MFA on Root Account
If MFA was not enabled on your root account — that is likely how you were compromised. Go to IAM Dashboard → Add MFA for root user. Use a hardware MFA device (YubiKey) or a virtual MFA app (Google Authenticator). Never use SMS for AWS root MFA — SIM-swapping attacks can intercept SMS codes.
Step 5: Check Billing and Payment Methods
Navigate to My Account → Payment methods to confirm no new credit cards or bank accounts were added. Check AWS Organizations if you use it — attackers may have linked new accounts to run up costs under your billing umbrella. Immediately set a billing alert via Billing → Billing preferences → Receive free tier usage alerts.
Phase 2: The First Hour — Comprehensive Assessment
Now that you have contained the immediate damage, you need to understand the full scope of the compromise. This is where CloudTrail becomes your most important tool.
Step 6: Enable CloudTrail If It Was Not Running
Go to CloudTrail → Trails → Create trail. Enable it for all regions, all management events, and S3 data events. If CloudTrail was already enabled, verify the trail status — attackers frequently disable CloudTrail as their first action to hide what they do next. Look for gaps in log files.
Step 7: Analyze CloudTrail Logs for Attack Timeline
Use the AWS Console CloudTrail Event History or the CLI to pull suspicious events. Key event names to investigate include:
# Look for IAM changes in the last 24 hours
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateUser --start-time 2026-03-14T00:00:00Z --output json
# Look for root account activity (any root usage is suspicious)
aws cloudtrail lookup-events --lookup-attributes AttributeKey=Username,AttributeValue=root --start-time 2026-03-07T00:00:00Z --output json
# Look for security group changes (attacker opening firewall rules)
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AuthorizeSecurityGroupIngress --start-time 2026-03-14T00:00:00Z --output json
# Look for S3 bucket policy changes
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=PutBucketPolicy --start-time 2026-03-14T00:00:00Z --output json
# Look for new Lambda functions (common cryptomining vector)
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateFunction20150331 --start-time 2026-03-07T00:00:00Z --output json
Step 8: Inventory All Active Resources Across All Regions
Attackers love to spin up resources in regions you do not normally use — ap-southeast-1, eu-central-1, sa-east-1, and af-south-1 are favorites because they are less monitored. Check every enabled region:
# List EC2 instances in each region
for region in us-east-1 us-east-2 us-west-1 us-west-2 eu-west-1 eu-central-1 ap-south-1 ap-southeast-1 ap-northeast-1 sa-east-1; do
echo "--- Region: $region ---"
aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].[InstanceId,InstanceType,State.Name,LaunchTime]' --output table 2>/dev/null
done
# Check for unexpected S3 buckets
aws s3api list-buckets --query 'Buckets[*].[Name,CreationDate]' --output table
# Check Lambda functions across regions
for region in us-east-1 us-east-2 us-west-2 eu-west-1 ap-southeast-1; do
echo "--- Lambda in $region ---"
aws lambda list-functions --region $region --query 'Functions[*].[FunctionName,LastModified,Runtime]' --output table 2>/dev/null
done
Step 9: Review GuardDuty Findings
If AWS GuardDuty is enabled, navigate to GuardDuty → Findings and filter by HIGH and CRITICAL severity. The most common findings after a compromise are:
- UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration — EC2 instance credentials used from an external IP address
- CryptoCurrency:EC2/BitcoinTool — EC2 instance communicating with cryptocurrency mining pools
- Backdoor:EC2/XORDDOS — EC2 instance used for distributed denial-of-service attacks
- Recon:IAMUser/MaliciousIPCaller — API calls from a known malicious IP address
- Persistence:IAMUser/UserPermissions — IAM permissions changed in a way that suggests persistence
Step 10: Check for S3 Data Exfiltration
If S3 Server Access Logging or CloudTrail data events are enabled, look for mass GetObject operations from unknown IP addresses. Also check bucket policies and ACLs for recently added public access:
# Check all bucket public access settings
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
echo "Checking $bucket..."
aws s3api get-bucket-public-access-block --bucket $bucket 2>/dev/null || echo " No public access block on $bucket"
done
# Look for buckets with public-read ACL
for bucket in $(aws s3api list-buckets --query 'Buckets[*].Name' --output text); do
acl=$(aws s3api get-bucket-acl --bucket $bucket --query 'Grants[?Grantee.URI!=null].Grantee.URI' --output text 2>/dev/null)
if [ -n "$acl" ]; then
echo "WARNING: $bucket has public ACL: $acl"
fi
done
Phase 3: Tracing the Initial Attack Vector
Step 11: Find How the Attacker Got In
Understanding the entry point is critical for preventing reoccurrence. The most common AWS compromise vectors are:
Exposed Access Keys in Code Repositories
Search your GitHub, GitLab, or Bitbucket repositories — including git history of deleted files — for any committed AWS access keys. Keys start with "AKIA" for long-term access keys or "ASIA" for temporary credentials. Use truffleHog, git-secrets, or GitHub's built-in secret scanning to sweep your repositories. Even if a key was committed and deleted five years ago, it may still be in git history and on the internet.
Phishing or Credential Theft
Look in CloudTrail for ConsoleLogin events. Check the source IP addresses. Use AbuseIPDB or VirusTotal to check if those IPs are known malicious infrastructure. Look for login times that do not match your team's working hours or login locations that do not match your team's geography.
SSRF Attack via EC2 Metadata Service
Server-Side Request Forgery (SSRF) attacks against the EC2 metadata endpoint at 169.254.169.254 allow attackers to steal temporary IAM role credentials through a vulnerable web application. Check your application logs for requests to the metadata service from user-controlled inputs. Protect against this by requiring IMDSv2 (session-oriented metadata) on all EC2 instances:
# Check if instances use IMDSv2 (required = secure, optional = vulnerable)
aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,MetadataOptions.HttpTokens]' --output table
# Enforce IMDSv2 on a specific instance
aws ec2 modify-instance-metadata-options --instance-id i-1234567890abcdef0 --http-tokens required --http-endpoint enabled
Step 12: Look for Persistence Mechanisms
Sophisticated attackers establish multiple backdoors. You must find all of them before closing access, or you will be re-compromised within hours. Check:
IAM Backdoors: New IAM users, new access keys on existing users, new IAM roles with trust policies pointing to external AWS accounts, new SAML or OIDC identity providers added to IAM, IAM policies modified to include new permissions.
# List all IAM identity providers (unexpected SAML/OIDC providers are backdoors)
aws iam list-saml-providers
aws iam list-open-id-connect-providers
# List all IAM roles and their trust policies
aws iam list-roles --output json | python3 -c "
import json, sys
data = json.load(sys.stdin)
for role in data['Roles']:
print(role['RoleName'], json.dumps(role['AssumeRolePolicyDocument']))
"
Lambda Backdoors: Lambda functions with event source mappings, API Gateway triggers, or CloudWatch Events schedules can run attacker code periodically. List and inspect all Lambda functions, especially any created recently.
CloudFormation Stacks: Check for unexpected stacks that may have deployed infrastructure resources you are not aware of.
EC2 AMIs: Attackers sometimes snapshot compromised instances and register them as AMIs to preserve their foothold.
Phase 4: Containment, Remediation, and Credential Rotation
Step 13: Isolate Compromised EC2 Instances
Do not terminate compromised instances immediately — you need them for forensic analysis. Instead, isolate them without destroying evidence:
- Create a "QUARANTINE" security group with no inbound rules and no outbound rules
- Assign only this security group to the compromised instance
- Detach the instance's IAM role (remove the instance profile)
- Take EBS snapshots of all attached volumes for forensic analysis
- Document everything before making changes
Step 14: Rotate Every Credential
Even after identifying the specific compromised credentials, rotate everything. You may have missed a backdoor:
- Delete all existing IAM access keys and create new ones for legitimate users
- Change all IAM console user passwords and require password reset at next login
- Rotate all secrets in AWS Secrets Manager
- Rotate all RDS and Aurora database master passwords
- Rotate any API keys stored in Lambda environment variables or ECS task definitions
- Regenerate any CloudFront signing keys
- Update all applications and services with the new credentials before deleting the old ones
Phase 5: Billing Dispute and AWS Support
Step 15: Document and Dispute Unauthorized Charges
Navigate to AWS Billing → Cost Explorer and identify all charges from resources you did not create or authorize. AWS has a process for waiving unauthorized charges from security incidents. When opening a support case:
- Use severity "Business Critical" (requires Business or Enterprise Support)
- Provide an incident timeline: when you believe the compromise started, when you discovered it, what actions you took
- Attach CloudTrail evidence showing the unauthorized resource creation
- Show that all compromised credentials have been revoked and replaced
- Demonstrate that you have implemented preventive controls
AWS frequently provides billing credits for first-time incidents where the customer acted quickly and in good faith. Document everything meticulously. A well-structured incident report greatly increases the chance of a full or partial credit.
Phase 6: Hardening Your AWS Account After Recovery
After recovery, implement these controls to prevent reoccurrence:
Root Account: Treat It Like Nuclear Launch Codes
- Never use root for day-to-day operations — create an admin IAM user instead
- Enable hardware MFA (YubiKey) on root — virtual MFA is acceptable but hardware is safer
- Remove all root access keys — there should be zero root access keys
- Store root credentials in a physical safe or encrypted offline vault, not in a password manager that is synced to the cloud
- Set up a CloudWatch Alarm for any root account login
IAM Hardening
- Enable MFA for all IAM users that have console access
- Set IAM password policy: minimum 14 characters, complexity required, 24-password history
- Use IAM roles instead of long-lived access keys wherever possible
- Enable AWS IAM Identity Center (SSO) for federated access instead of individual IAM users
- Use Service Control Policies (SCPs) in AWS Organizations to establish hard guardrails even for admin accounts
- Enable IAM Access Analyzer to continuously detect overly permissive policies
Detection and Monitoring
- Enable AWS CloudTrail in all regions with log file validation and S3 log encryption
- Enable AWS GuardDuty in all regions — at roughly $3 per million CloudTrail events, it costs less than a coffee per month for most accounts
- Enable AWS Security Hub to centralize findings from GuardDuty, Inspector, Macie, and Config
- Enable AWS Config to track all configuration changes with compliance rules
- Set up CloudWatch Alarms for: root logins, IAM policy changes, CloudTrail configuration changes, security group changes, network ACL changes, and MFA disabled events
Network and Compute Security
- Require IMDSv2 on all EC2 instances — this alone prevents the majority of SSRF-based credential theft attacks
- Enable VPC Flow Logs to track all network traffic
- Use AWS WAF on all public-facing applications and APIs
- Never allow 0.0.0.0/0 on port 22 (SSH) or 3389 (RDP) in security groups — use AWS Systems Manager Session Manager instead
Data Protection
- Enable S3 Block Public Access at the account level — this is a single toggle that prevents all public S3 bucket access regardless of individual bucket settings
- Enable S3 MFA Delete on critical buckets so attackers cannot delete data or version history
- Enable S3 Object Lock on backup buckets with Compliance mode for immutable backups
- Encrypt all EBS volumes, RDS instances, and S3 buckets — use AWS KMS with customer-managed keys for sensitive data
The Real Cost of Not Preparing
A single AWS account compromise can generate $50,000 to $500,000 in unauthorized charges within 48 hours. Attackers who find AWS credentials do not sit idle — automated tools immediately begin spinning up the most expensive instances available (p4d.24xlarge GPU instances at $32/hour, hundreds of them, across a dozen regions) for cryptocurrency mining or renting compute to other criminals.
GuardDuty costs roughly $3.50 per million CloudTrail events. That is less than $5 per month for most small accounts. The cost of one incident without it: your entire annual cloud budget, plus weeks of incident response, plus the reputational damage of explaining to customers why their data may have been exfiltrated.
If you need help hardening your AWS environment, conducting a security posture assessment, or setting up a proper cloud incident response plan, ZeonEdge's cloud security team is here to help. Contact us for a free security consultation.
태그
Sarah Chen
Senior Cybersecurity Engineer with 12+ years of experience in penetration testing and security architecture.