SecurityEC2AWS

Detecting Unauthorized EC2 Instances Before AWS Does

Viktor B.

Co-founder & CEO · November 20, 2025 · 7 min read

The first sign that something is wrong is usually the AWS bill. An account that normally runs $800 a month in EC2 charges suddenly shows $12,000 in a single week. By the time the bill appears in Cost Explorer, the unauthorized instances have been running for days, consuming budget, generating outbound traffic, and — in the case of crypto mining — putting the account at risk of suspension for violating AWS's acceptable use policy.

The goal isn't to detect unauthorized instances after the bill arrives. It's to detect them within minutes of launch, before the damage accumulates. This is achievable with the right combination of CloudTrail alerting, GuardDuty, and billing anomaly detection — none of which requires expensive third-party tools.

Why Unauthorized Instances Happen

There are three common root causes, each requiring a different detection approach.

Credential compromise. An IAM access key is leaked — in a public GitHub repository, in an exposed CI/CD log, in an S3 bucket with public read access. An attacker finds the key, tests its permissions, and launches EC2 instances for crypto mining or botnet infrastructure. The attacker knows they have a limited window before the key is revoked, so they launch as many high-powered instances as they can as quickly as possible. Attackers specifically target high-CPU and high-GPU instance types for this reason.

Insider threat or shadow IT. A developer launches instances in a region or account they're not supposed to be working in. This might be intentional policy violation, accidental use of the wrong account, or well-intentioned experimentation that never gets cleaned up. These instances often run for months before anyone notices.

Misconfigured automation. A Terraform misconfiguration, a runaway auto-scaling policy, or a CloudFormation stack that creates more resources than intended. These aren't malicious, but the cost and risk profile is similar — resources running that nobody knows about and nobody will clean up without intervention.

Real-Time Detection via CloudTrail + EventBridge

Every EC2 instance launch generates a RunInstances CloudTrail event. EventBridge can match this event and trigger a Lambda function or SNS notification within seconds of the API call. This is the fastest detection mechanism available for unauthorized launches.

Create an EventBridge rule with the following event pattern:

{
  "source": ["aws.ec2"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventName": ["RunInstances"]
  }
}

Route matching events to a Lambda function that checks the launching IAM principal, the instance type, and the region against an allow-list. Flag launches of high-powered instance types (c5.18xlarge, p3.8xlarge, p4d.24xlarge) from unexpected principals or in regions where your organization doesn't normally operate. Send an alert through SNS to a security channel and the account owner.

This approach has essentially no false positive problem if your allow-list is accurate. Most organizations launch EC2 instances from a small set of automation roles and developers — a launch from an IAM access key attached to a CI/CD system is immediately suspicious if that system isn't normally provisioning EC2.

GuardDuty as a Second Line of Defense

GuardDuty's Backdoor:EC2/C&CActivity.B and CryptoCurrency:EC2/BitcoinTool.B findings detect mining activity and command-and-control communications from running instances. These findings fire based on network behavior, not API calls — they catch cases where the launch itself appeared legitimate but the instance is being used maliciously.

Enabling GuardDuty in all regions is essential here. Attackers specifically launch mining instances in regions where organizations don't monitor, knowing that GuardDuty-equivalent alerts will only fire in regions where the service is enabled. A region with no workloads still needs GuardDuty enabled — mining instances in that region generate no legitimate traffic to create noise, making detection actually easier.

See the full GuardDuty setup guide for organization-wide deployment and GuardDuty finding response playbooks for how to respond when these findings fire.

Billing Anomaly Detection as a Backstop

CloudTrail alerting and GuardDuty are the right primary detection tools. AWS Cost Anomaly Detection is the backstop for cases they miss — an EC2 launch that looks legitimate on its face but generates unexpected spend. Configure Cost Anomaly Detection with a threshold appropriate for your normal EC2 spend variance, and route alerts to the same security channel as your CloudTrail alerts.

The limitation of billing anomaly detection is latency. Cost data arrives with a multi-hour delay, and anomaly alerts are typically generated the next morning. By then, a credential compromise attack may have run for 12-24 hours. Use billing anomaly detection as confirmation and for longer-running unauthorized resource patterns, not as your primary detection tool.

See the detailed guide to AWS billing anomaly detection for threshold configuration and alert setup.

Prevention: Permissions That Limit Blast Radius

Detection speed matters, but prevention reduces the damage window. Apply least-privilege IAM policies that restrict which instance types can be launched, which regions EC2 APIs can be called in, and which AMIs can be used. A Service Control Policy at the Organizations level that denies ec2:RunInstances for GPU and high-CPU instance types unless the request comes from an approved automation role means a compromised developer credential can't launch mining infrastructure regardless of what the developer's IAM policy allows.

For organizations with multi-account AWS environments, consider restricting high-powered instance type launches to a specific "compute" account that has additional monitoring controls. This limits the blast radius of any single account compromise.

Related Reading

FAQ

How quickly can I detect an unauthorized EC2 launch?

With EventBridge rules watching for RunInstances CloudTrail events, detection time is typically under 60 seconds from when the API call is made. CloudTrail delivers events to EventBridge with very low latency. A Lambda function triggered by the event can check the launch against policy and send an alert to Slack or PagerDuty within the same minute.

Can I use SCPs to prevent unauthorized instance types from being launched?

Yes. A Service Control Policy with a Deny effect on ec2:RunInstances conditioned on the instance type is an effective preventive control. Use the ec2:InstanceType condition key to restrict which instance types are permitted. SCPs apply to all principals in the account including the root user (with some exceptions) and override individual IAM permissions.

What should I do if I find unauthorized instances running?

Stop and terminate the instances immediately. Revoke the credentials used to launch them — rotate the IAM access key if a key was compromised, or disable the role if a role was used. Review CloudTrail logs for the compromised principal to identify any other actions taken with the credentials. If the account is an AWS Organizations member, check other accounts in the organization for similar activity using the same principal. File a report with AWS Support documenting the incident.

Protect your AWS accounts before it's too late

Vigilare monitors your AWS accounts for suspension risks — billing anomalies, IAM issues, GuardDuty findings, and more — and alerts you before AWS takes action.

Written by Viktor B.

Co-founder & CEO