Description

Ensure that no Amazon Machine Image (AMI) owned by the account is shared publicly. An AMI is public when its launch permissions include all AWS accounts (Group=all), which allows any AWS account to launch instances from it.

Rationale

A public AMI exposes its full contents to every AWS account. This can leak embedded secrets, credentials, configuration files and data from the snapshots behind the image, and it lets attackers study your software stack to plan targeted attacks or reuse the image for supply chain abuse. AMIs should be private and shared only with specific accounts that need them. Block public access for AMIs should also be enabled, and images should be cleaned of secrets before sharing.

Impact

  • Prevents unknown accounts from launching instances from your AMIs and reading their contents

  • Reduces the risk of leaking secrets and internal configuration

  • Accounts that currently launch instances from the public AMI lose access unless the AMI is shared with them explicitly

Default Value

AMIs are private by default when created.

Pre-Requisites

  • IAM permissions: ec2:DescribeImages, ec2:DescribeImageAttribute, ec2:ModifyImageAttribute and ec2:EnableImageBlockPublicAccess

  • A list of AWS accounts that still need access to each AMI, so it can be shared with them explicitly

Remediation

Test Plan

Console:

  1. Sign in to the AWS Management Console at https://console.aws.amazon.com.

  2. Open the Amazon EC2 console and select AMIs under Images.

  3. Choose the Owned by me filter.

  4. Check the Visibility column of each AMI.

  5. Repeat for each region in use.

  6. If any AMI has visibility Public, follow the implementation steps.

CLI:

List the public AMIs owned by the account, including deprecated ones:

aws ec2 describe-images --owners self --include-deprecated --region <REGION> --query "Images[?Public==\`true\`].[ImageId,Name]" --output table

An AMI fails if it is listed by this command.

Implementation Steps

Console:

  1. Sign in to the AWS Management Console at https://console.aws.amazon.com.

  2. Open the Amazon EC2 console and select AMIs under Images.

  3. Select the AMI with visibility Public.

  4. Choose Actions, then Edit AMI permissions.

  5. Under AMI availability, select Private.

  6. If other accounts still need the AMI, add their account IDs under Shared accounts.

  7. Choose Save changes.

  8. Repeat for each affected AMI in each region in use.

CLI:

Remove public launch permission from the AMI:

aws ec2 modify-image-attribute --image-id <AMI_ID> --region <REGION> --launch-permission "Remove=[{Group=all}]"

Share the AMI with a specific account if it is still needed:

aws ec2 modify-image-attribute --image-id <AMI_ID> --region <REGION> --launch-permission "Add=[{UserId=<ACCOUNT_ID>}]"

Block any new public sharing of AMIs in the region:

aws ec2 enable-image-block-public-access --image-block-public-access-state block-new-sharing --region <REGION>

Backout Plan

Before making changes, save the current launch permissions:

aws ec2 describe-image-attribute --image-id <AMI_ID> --attribute launchPermission --region <REGION> > ami-permissions-backup.json

To roll back:

  1. Sign in to the AWS Management Console at https://console.aws.amazon.com.

  2. Open the Amazon EC2 console and select the AMI under AMIs.

  3. Choose Actions, then Edit AMI permissions.

  4. Select Public (block public access for AMIs must be disabled first).

  5. Choose Save changes.

CLI:

aws ec2 disable-image-block-public-access --region <REGION>
aws ec2 modify-image-attribute --image-id <AMI_ID> --region <REGION> --launch-permission "Add=[{Group=all}]"

Note: rolling back makes the AMI and its contents available to every AWS account again.

Reference