What is IMDSv2
The instance metadata service (IMDS) is an on-instance component that code on the instance uses to securely access instance metadata.
In November 2019, AWS made IMDSv2 available. They consider this the belt and braces approach to instance metadata security.
Let's look at an example retrieving the AMI ID using IMDS:
The old approach
curl http://169.254.169.254/latest/meta-data/ami-id
The new approach
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
curl http://169.254.169.254/latest/meta-data/ami-id -H "X-aws-ec2-metadata-token: $TOKEN"
Important side note: Sessions can last a maximum of 6 hours (21600 seconds).
As you can see, there are two key differences.
- We first use a PUT call to retrieve a time sensitive session token
- We then pass this token through to each request to authorise them
Protecting against SSRF vulnerabilities
IMDSv2 helps protect against SSRF vulnerabilities (server side request forgery).
There is at least one high profile breach linked to IMDSv1 usage in a well known bank. This highlights the need for a defense in depth approach while securing your cloud access.
It is thought that the credentials for the IAM Role were pulled from the instance metadata. Unfortunately, the role attached may have had excessive privileges allowing access to S3 storage. Once the hacker has access to credentials like this then it is game over.
A key difference in IMDSv2 is utilising PUT rather than GET.
GET requests are notorious for leaking credentials, so using a PUT request in combination with a session token helps mitigate a lot of the risk.
Is my application still using IMDSv1?
AWS have a cloudwatch metric for this called MetadataNoToken.
- The number of times the instance metadata service was successfully accessed using a method that does not use a token.

How to require IMDSv2 on EC2
When launching an EC2 using terraform this can be specified using metadata_options:
resource "aws_instance" "example" {
// ...
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
}
}
Otherwise the default value will be "optional"
How to enforce the use of IMDSv2
Here is an example policy to enforce IMDSv2 as per this guide:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RequireImdsV2",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:MetadataHttpTokens": "required"
}
}
}
]
}
Summary
In a nutshell, every request in IMDSv2 is now protected by session authentication. Updated AWS SDKs and CLIs use this by default, but when writing our scripts we need to make sure we are also using the new format.
This is a cheap and effective way to help mitigate SSRF attacks.