Articles / The Cloud Metadata Service and SSRF: IMDSv1 vs IMDSv2
Cloud · SSRF

The Cloud Metadata Service and SSRF: IMDSv1 vs IMDSv2

There is an address every cloud instance can reach and almost no one configures on purpose: 169.254.169.254. It is the instance metadata service, and it exists to answer a bootstrapping question — "who am I, and what credentials do I get?" The problem is that a server-side request forgery bug can make your application ask that question on the attacker's behalf, and the answer is a set of working cloud credentials.

The Instance Metadata Service (IMDS) is a link-local HTTP endpoint available to every VM in AWS, Azure, and Google Cloud. It serves instance details and, crucially, temporary IAM credentials for the role attached to the machine. Those credentials let the workload call cloud APIs without embedded secrets — a genuinely good design. The danger is that the metadata endpoint trusts anything that can send it an HTTP request from the instance, and a web application with an SSRF flaw is exactly such a thing.

How the attack works

crafted URLforged requestAttackerWeb app withan SSRF flawMetadata service169.254.169.254Instance rolecredentialsCloud APIas the instanceIMDSv1: any GETreturns credentials
An SSRF bug turns the metadata endpoint into a credential vending machine.

SSRF lets an attacker coax a server into making requests to a URL the attacker chooses. Point that at the metadata IP and, on a vulnerable instance, the server fetches its own role credentials and returns them in the response. The attacker now holds the instance's identity and can call the cloud API directly, with whatever permissions that role carries. The 2019 Capital One breach is the canonical public example: an SSRF weakness was used to reach the EC2 metadata service and retrieve credentials, which were then used to access data in S3.

SSRF reaching the metadata endpoint (AWS IMDSv1)GET /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ → role name → GET .../iam/security-credentials/<role> → AccessKeyId, SecretAccessKey, Token

IMDSv1 vs IMDSv2

AWS's answer was IMDSv2, a session-oriented scheme that closes the SSRF path without changing what metadata contains. The difference is in how you ask:

  • IMDSv1 is a simple request/response: any GET to the metadata IP returns the data. That is precisely what a basic SSRF can forge, because most SSRF primitives only control a URL.
  • IMDSv2 requires a session token first. You PUT to /latest/api/token to obtain a short-lived token, then send it in the X-aws-ec2-metadata-token header on every request. A URL-only SSRF cannot issue a PUT or set a custom header.
  • A hop-limit default of 1 stops the token response from being routed off the instance, blocking container and proxy relays.
  • Enforcement matters. IMDSv2 only helps when v1 is disabled; leaving both enabled means an attacker just uses the easy one.
Why it matters: The metadata service is the shortest path from a web-app bug to cloud API access. It turns an SSRF — often rated medium severity in isolation — into full credential theft.

The other clouds, and the broader fix

Azure and Google Cloud take a header-based approach: Azure's IMDS requires the request to carry Metadata: true, and GCP's metadata server requires Metadata-Flavor: Google. Both refuse requests that also carry certain headers, defeating naive SSRF that can only set a URL. As with IMDSv2, this raises the bar but is not absolute — an SSRF that can control headers, or a full request-forgery primitive, can still get through.

  • Enforce IMDSv2 and disable v1 across every instance and launch template; require it at the account level so new machines inherit it.
  • Set the metadata hop limit to 1 and block egress to 169.254.169.254 from application code that has no reason to reach it.
  • Fix the SSRF at the source. Validate and allowlist outbound URLs, resolve and pin destinations, and reject link-local and private ranges.
  • Right-size the instance role. If credentials are stolen, least privilege decides whether the blast radius is one bucket or the whole account.

IMDSv2 is one of the rare mitigations that neutralises an entire attack class with a single enforced setting — but only on the instances you know to configure. The metadata endpoint answers the same question everywhere, which is why the workloads you have not inventoried are the ones still running v1: you can't defend what you haven't discovered.

Test for it — in practice
  • Check the metadata options on your instances and launch templates and see whether IMDSv1 is still permitted — if both versions are enabled, an attacker just uses the easy one.
  • Confirm the metadata hop limit is set to 1 so the token response cannot be relayed off the instance.

Verifying a template or two is quick; finding every instance still exposing v1 across accounts and regions is what our assessment runs for you.

Keep reading
Lateral Movement in the Cloud After Initial Access