TL;DR If you are just interested in how to enable this feature, go to “How do we enable and test this new feature”
This blogpost is about a recently released update to AWS EC2 instance metadata service (IMDSv2) for improving security and adding an additional defence in depth layer. In this post you will learn how to migrate an EC2 instance to IMDSv2. We will also cover how to rollback the change to IMDSv1 in case you face any issues.
Why did AWS release Version 2 of AWS EC2 Instance Metadata service (IMDSv2)
In mid-November 2019, AWS released an update to EC2 instance metadata service which is used for querying instance metadata values. This new release according to AWS is a defence in depth against open firewalls, reverse proxies and SSRF vulnerabilities. IMDSv2 needs a session token for making any request to the service. This token can only be obtained by making a specific request using the
HTTP PUT method.
The service which was initially introduced a decade ago in 2009, has been widely used to exploit Server Side Request Forgery (SSRF) vulnerabilitiesin web applications running on EC2. Any security tester who ever found a vulnerability in an application running on EC2 were able to call the version 1 of instance metadata service to discover
AWS STS token and find out more about privileges and Identity Access Management (IAM) roles it has. The metadata endpoint runs on a link-local IP address and uses HTTP GET requests.
With the new update, AWS has introduced a token based authentication for requesting data with the endpoint and in order to get the token a separate PUT request must be made. According to IMDSv2 introduction blog post, AWS looked at multiple real-world attacks. This combination of getting the token secret first and then further using the token to perform successive requests helps in mitigating most SSRF attacks.
The move to using
HTTP PUT method to initiate the session is to protect against misconfigured Web Application Firewall (WAF) that allows requests to EC2 instances. Most open WAFs do not support PUT requests.
AWS released a useful CloudWatch metric for discovering all the instances that access metadata endpoint without any token.
How do we enable the security token to test IMDSv2
We will create a role
role-to-access-parameter-store with permission to access Parameter Store (Systems Manager) and attach it to the instance, to understand the use of IMDS. We will create another instance without a role which means it should not make calls like the one with a role. To view this, we will head to Metrics in CloudWatch service where we can create graphs with specific metrics. Under All metrics, select
EC2 -> Per-Instance Metrics and from there select
MetadataNoToken metric for the instances.
Now we can try querying the metadata service from the machines and see a corresponding spike in the graph, because the metric defines a value if metadata endpoint is requested without security token.
Now that we can monitor the difference between IMDSv1 and IMDSv2 requests, we will go ahead and enable IMDSv2 in both the instances. To do this, we will use
aws-cli. An update was released for
aws-cli with the option to enable and disable IMDSv2 under EC2.
To install/update your
aws-cli you could do,
pip3 install awscli# If running python2 version
pip install awscli
Once we upgrade our aws-cli version to
aws-cli/1.16.287 Python/3.6.8, we access the command option
modify-instance-metadata-options under EC2. Let’s enable IMDSv2, by running the following command,
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE-ID> --profile <AWS_PROFILE> --http-endpoint enabled --http-token required
<INSTANCE-ID>— ID of the instance that you want to enable IMDSv2.
<AWS_PROFILE>— Profile name you have configured for API keys in
Once security tokens are enabled, when we try to do the curl request to instance metadata endpoint we get
401 Unauthorized as response without the token
Now that we have confirmed that IMDSv2 is enabled, we can generate the token for accessing metadata endpoint with the below
HTTP PUT request and store the token in a environment variable
export TOKEN=`curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" "http://169.254.169.254/latest/api/token"`
For further calls, we will use the security token obtained as part of the HTTP request header,
curl -H "X-aws-ec2-metadata-token:$TOKEN" -v "http://169.254.169.254/latest/meta-data"
Value of $TOKEN is from the shell environment.
You can see the difference now in CloudWatch metric graph by making few requests to the metadata endpoint. The graph will not show any activity anymore, since the requests are now made with Security Token.
How to disable security token to rollback from IMDSv2
If you would like to disable IMDS v2 and do not want the restriction of having tokens to make calls to Metadata endpoint, you can use the below command to perform the same,
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE_ID> --profile <PROFILE_NAME> --http-endpoint enabled --http-token optional
All in all, this has been a welcome update to what was a very long expected solution from AWS. This update helps add an additional layer to web applications running on EC2 instances from making a high severity vulnerability into a lower one.
At Appsecco we provide advice, testing and training around software, infra, web and mobile apps, especially that are cloud hosted. We also specialise in auditing AWS environments as per the AWS CIS Foundations Benchmark to create a picture of the current state of security in your AWS environment. Our experience has led us to creating multiple hands on training courses like the very popular “Breaking and Pwning Apps and Servers on AWS and Azure” and “Automated Defence using Cloud Services for AWS, Azure and GCP”.
Drop us an email, firstname.lastname@example.org if you would like us to assess the security of your AWS infrastructure or if you would like your security team trained in advanced pentesting techniques against AWS.