Tools · Cloud security · 14 / 24
What is IMDSv2 and how to enforce it on EC2
Understand why the instance metadata service is a target for SSRF, how IMDSv2’s session tokens help, and how to require it on existing and new instances.
Metadata holds credentials
Every EC2 instance can reach the instance metadata service at 169.254.169.254. Among other things, it serves temporary credentials for the instance’s IAM role. If a web application on the instance has a server-side request forgery bug, an attacker can make the application fetch those credentials and use them from anywhere. That was a key step in several well-known cloud breaches.
IMDSv1 answers any GET request. IMDSv2 requires a session token obtained with a PUT request and a custom header, which most SSRF bugs cannot produce, and it refuses requests that carry an X-Forwarded-For header.
Check and require
describe-instances shows MetadataOptions.HttpTokens: optional means v1 is still allowed; required means v2 only. modify-instance-metadata-options changes it without a reboot. Set HttpPutResponseHopLimit to 1 so containers on the host cannot reach metadata through an extra network hop, unless they need it.
Account-level defaults and launch templates can make required the default for new instances.
aws ec2 describe-instances --query 'Reservations[].Instances[].{id:InstanceId,tokens:MetadataOptions.HttpTokens,hop:MetadataOptions.HttpPutResponseHopLimit}' --output table
aws ec2 modify-instance-metadata-options --instance-id i-0123456789abcdef0 --http-tokens required --http-put-response-hop-limit 1
aws ec2 modify-instance-metadata-defaults --http-tokens requiredLab: v1 versus v2 from inside the instance
On a sandbox instance with HttpTokens optional, request the role credentials path with a plain curl and see it succeed. Change to required and repeat: the plain request now returns 401. Then do the v2 sequence with a token and see it work.
Before enforcing on real instances, check CloudWatch’s MetadataNoToken metric, which counts v1 calls, to find software that still uses v1 and needs updating.
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token -H 'X-aws-ec2-metadata-token-ttl-seconds: 300') curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/
Defense in depth
IMDSv2 reduces SSRF risk but does not fix the SSRF bug. Fix the application, restrict outbound requests from it, and keep the instance role narrow so stolen credentials are worth little.
GuardDuty’s InstanceCredentialExfiltration findings detect role credentials used outside AWS, which is the signal that something got through.
Diagram
IMDSv1 versus IMDSv2
What an SSRF bug can fetch.
Request. Any GET to 169.254.169.254.
SSRF. Usually able to read role credentials.
Status. Should be disabled.
Request. PUT for a token, then GET with a header.
SSRF. Most bugs cannot perform the PUT with headers.
Extra. Hop limit 1 blocks containers.
Check yourself
1. Why is IMDSv1 risky?
2. Which setting enforces IMDSv2?
3. Which metric shows software still using IMDSv1?