EC2 Instance Metadata Service (IMDS)
The Instance Metadata Service is a link-local HTTP API attached to every EC2 instance, reachable at 169.254.169.254 (IPv4 link-local, see ipv4-address-representations) or [fd00:ec2::254] on IPv6-enabled Nitro instances. It exposes data about the running instance — hostname, AMI ID, network interfaces, security groups, user data — and, critically, temporary IAM credentials for any instance role, under:
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
AWS’s own documentation warns that metadata is “not protected by authentication or cryptographic methods” — anyone (or any process) on the instance can read it, which is precisely what makes it an attack surface.
IMDSv1 vs IMDSv2
| IMDSv1 | IMDSv2 | |
|---|---|---|
| Style | Plain GET request/response | Session-oriented: PUT /latest/api/token first, then GETs with X-aws-ec2-metadata-token header |
| Token | none | Opaque token, TTL 1s–6h, bound to the instance |
| SSRF resistance | Low — a GET is trivially forged by most SSRF bugs | Higher — SSRF must support HTTP PUT and custom headers to mint a token |
| Default | Enabled alongside v2 (must be explicitly disabled) | Available since Nov 2019 |
IMDSv2 token acquisition:
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/An instance can be hardened to require IMDSv2 (HttpTokens=required), which causes IMDSv1 calls to fail.
Why it matters: SSRF → credential theft
The canonical cloud SSRF exploit chain is:
- Attacker finds an SSRF vulnerability in an app on an EC2 instance (or an open proxy / misconfigured reverse proxy).
- They coerce the server into requesting
http://169.254.169.254/latest/meta-data/iam/security-credentials/. - The response yields temporary
AccessKeyId/SecretAccessKey/Tokenfor the instance role — usable from anywhere until expiry.
AWS introduced IMDSv2 specifically as “belt and suspenders” defense against four vulnerability classes: open firewalls, open reverse proxies, SSRF, and open layer-3 firewalls/NAT. The session-oriented PUT + header requirement defeats naive SSRF payloads that can only issue GETs without custom headers. Defense-in-depth still applies: least-privilege instance roles, local firewall rules blocking metadata access from app users, and requiring IMDSv2.
Recon angle
On a compromised instance (or via SSRF), the metadata service answers “what is this box?” — instance ID, VPC/subnet, IAM role name, and whether the role is worth escalating toward. Combine with aws-ssm-ssh (SSM agent presence is visible via the AmazonSSMRoleForInstancesQuickSetup-style role names) and aws-ecs-exec for container-task credential endpoints, which use a different URI (169.254.170.2) but the same trust model.
See also
- ipv4-address-representations — 169.254.169.254 in decimal/hex for filter-bypass payloads (e.g.
2852039166,0xa9fea9fe) - aws-root-account-email-discovery — what to do with stolen credentials next
- aws-sigv4-api-flooding — using harvested credentials against SigV4 APIs