EC2 instance created using risky AMI search pattern
Goal
Detect when an EC2 instance is instantiated using a vulnerable AMI search pattern.
Strategy
This rule allows you to monitor CloudTrail and detect when EC2 instances are created in a way that is vulnerable to a type of supply chain attack known as a name confusion attack. When this rule triggers, it does not mean an attack was successfully executed. Rather, it means that the way AMI IDs are being searched for is vulnerable to a name confusion attack. Unless the software is updated, an attacker who publishes an AMI that matches the search pattern used could gain remote code execution in the affected AWS account.
The rule triggers when both of the following conditions are met:
ec2:DescribeImages
is called without specifying the owner
parameter- Subsequently, the same IAM principal executes a call to
ec2:RunInstances
The two CloudTrail events covered by this rule are:
An AWS CLI example that would trigger this rule:
Find the AMI ID using ec2:DescribeImages
with a filter and without specifying the owner
parameter:
AMIID="$(aws ec2 describe-images --filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*" --query "Images[0].ImageId" --output text)"
Create the EC2 instance using the retrieved AMI ID:
aws ec2 run-instances --image-id "$AMIID" --instance-type t3.micro --subnet-id "$SUBNETID"
This rule inspects all ec2:DescribeImages
events and specifically the @requestParameters.filterSet.items
array to determine if the name
key is used, which indicates the user is looking for an AMI by name. The rule then filters out all of the cases where the user included protections that would prevent exploitation, for instance, by using the @requestParameters.ownersSet.items.owner
attribute or by requesting a specific AMI by ID. The rule also filters out all instances where the user has set -@requestParameters.executableBySet.items.user:self
which would limit the results to self hosted AMIs.
The rule also includes a subsequent check to see if the same ARN that made the insecure query above also creates an EC2 instance shortly thereafter. This prevents false positives for when people manually use ec2:DescribeImages
without ever using that data to create an EC2 instance.
The likelihood of exploitation for this vulnerability depends on the search filter used for the AMI. If the query string is a common AMI name pattern like ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*
or amzn2-ami-hvm-2.0.*-x86_64-gp2
, the likelihood of exploitation is greater. If the query string is unique to your organization, like orgname-devops-xyz-image-*
, it typically limits exploitation to actors with knowledge of the image name pattern, such as developers.
Triage and response
- Investigate the ARN (
{{@userIdentity.arn}}
) that made the these calls. - Contact the user and attempt to identify the code that triggered this rule.
- Work with the code owner to ensure they add one of the attributes in the
ec2:DescribeImages
call that limits the returned AMIs to those that are trusted. These include:- Owner attribute:
Owner=[AccountID, self, amazon, aws-backup-vault, and aws-marketplace]
- Filter:
owner-alias=[amazon, aws-marketplace, aws-backup-vault]
- Filter:
owner-id=[AccountID]
- Consider using AWS’s Allowed AMIs guardrail to limit which accounts are trusted to serve AMIs within your environment. This control can be enforced at an account/region level, or at an organization level.
Known false positives and limitations
This detection relies on two separate CloudTrail events, executed by the same ARN, occurring in succession. However, CloudTrail does not contain all of the information needed to tie the two events together conclusively. It is possible that the ARN making the insecure ec2:DescribeImages
call happens to subsequently call ec2:DescribeImages
in a way that is unrelated to the insecure ec2:DescribeImages
call. The best course of action is to find the user or code that made the ec2:DescribeImages
call and determine if they used the result of the ec2:DescribeImages
to create an EC2 instance.
The ec2:DescribeImages
CloudTrail event does not contain any information to indicate how the principal handled the data that came back. For example, from the CloudTrail event alone, there is no way to determine if the caller sorted the results by most recent creation date, simply used the first returned results, etc.