Alye / Resources / Blog
Blog

Requiring IMDSv2 closes more attack paths than you think

How instance metadata turns a web bug into stolen cloud credentials, how to find what still uses IMDSv1, and how to switch an account over without breaking anything.

By the Alye team6 min readAWSAttack paths

When we map attack paths in AWS accounts, one step shows up again and again: an internet-facing EC2 instance that still allows version 1 of the instance metadata service. Requiring IMDSv2 is a one-line change, it rarely breaks anything, and it often closes several paths at once. Here is why, and how to roll it out safely.

Why instance metadata matters

Every EC2 instance can ask the metadata service at 169.254.169.254 about itself, including for temporary credentials of the IAM role attached to it. With IMDSv1, that is a plain HTTP GET. So if an application on the instance can be tricked into fetching a URL for an attacker (server-side request forgery, or SSRF), the attacker can ask it to fetch the role's credentials and then use them from anywhere. The widely reported 2019 Capital One breach followed this pattern: an SSRF on a web-facing server, then the role's credentials, then the role's access to S3.

What IMDSv2 changes

IMDSv2 requires a session token first, obtained with an HTTP PUT that carries a special header, and then that token on every request. Most SSRF bugs can only make the application send simple GETs, so they can't get a token. The PUT response is also limited to one network hop by default, so it doesn't travel beyond the instance. That one change removes the “SSRF to credentials” step from the path.

Find what still uses IMDSv1

  • Per instance: the CloudWatch metric MetadataNoToken counts metadata calls made without a token. Zero over a couple of weeks means nothing on the instance depends on IMDSv1.
  • Per account: list instances whose MetadataOptions.HttpTokens is optional. Those are the ones to look at, internet-facing ones first.
  • Software: current AWS SDKs and the CLI use IMDSv2 already. Old SDK versions, and scripts that call the metadata URL directly with curl, are the usual reasons a non-zero count stays non-zero.

Switch it on

For a running instance, no restart needed:

aws ec2 modify-instance-metadata-options \
  --instance-id i-0123456789abcdef0 \
  --http-tokens required --http-endpoint enabled

For new instances, set it where they come from:

  • Terraform: metadata_options { http_tokens = "required" } on instances and launch templates.
  • Account default: aws ec2 modify-instance-metadata-defaults --http-tokens required in each region makes it the default for new launches.
  • Guardrail: a service control policy that denies ec2:RunInstances unless ec2:MetadataHttpTokens is required stops new IMDSv1 instances across an AWS Organization.

One thing to check: containers

Containers on EC2 that use bridge networking are one network hop further from the metadata service. If they rely on the instance role, set the hop limit to 2 (--http-put-response-hop-limit 2) when you require tokens. Better still, give them their own role (for example ECS task roles or EKS pod identities) so they don't need the instance's credentials at all.

Why it ranks high

On its own, “IMDSv1 allowed” is a medium finding. On an instance that faces the internet and runs as a role that can read customer data, it is the cheapest link to break on a route to that data. That is why it comes near the top of a ranking built on attack paths rather than severity alone.

See this in your own cloud. Alye Security connects read-only and ranks every issue by what an attacker could reach.

Book a demo

Related on Alye

More from the blog

Get started

Ready to put Alye on duty?

First trace right away. First ranked scan in about fifteen minutes.

Start free Read the docs