AWS Instance Metadata Version 2 Enhancements (IMDSv2)

Introduction

Amazon introduced version 2 of the AWS metadata service called Instance Meta Data Service version 2 (IMDSv2) in November 2019 which promises to protect against all exploitation attempts to access the metadata service via vanilla SSRF weaknesses.

What are we going to cover?

In this chapter, we will update the metadata service on our target to version 2 and see how our attacks fail and why the update actually secures the Instance metadata service.

What problem did the update solve?

Server Side Request Forgery can be an extremely lucrative finding to an attacker because of the ability to make requests from the target machine. When discovered on a cloud instance, things get a little more interesting as attackers can access the metadata instance, available via a APIPA range IP address over HTTP - http://169.254.169.254/, and accessible only from the target. For AWS this has always been a cause for concern as there was no authentication present to access this instance, and no requirement for a custom header that both GCP and Azure have.

As we have seen in our examples so far, in the most simple cases of an SSRF, a request to an attacker supplied URL is made from the server. For example, if there is a web application running on an AWS EC2 instance, a user supplied input like http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name would initiate a web request to the endpoint from the AWS EC2 resulting in a response being sent back to the client.

This works because

  1. The most basic form of SSRF is a GET based vulnerability. A response for a user supplied URL is fetched via a HTTP GET request by the vulnerable web app/web server.

  2. There is no authentication at the Instance Metadata endpoint. This allows for a simple GET request with no additional/custom headers to retrieve information.

The new Instance Metadata Service v2 (IMDSv2) tackles both of these conditions. IMDSv2 adds the following exploit mitigating changes to access the endpoint

  1. The requirement of a HTTP header called x-aws-ec2-metadata-token that contains a value generated via a PUT request to http://169.254.169.254/latest/api/token

  2. A PUT request to http://169.254.169.254/latest/api/token with the custom header x-aws-ec2-metadata-token-ttl-seconds with the value of the number of seconds for which the token needs to be active. This PUT request generates the token to be used in Step 1.

For a SSRF to succeed with this update, the attacker would need to be able to control the HTTP Method (force server to make a PUT instead of the standard GET) and be able to pass custom headers to the server, which the server then will use to make the requests.

This update fixes all vanilla SSRF where the attacker can only control the target URL.

Steps to complete the exercise

To change the version of the metadata instance, we need to know the instance-id of the target compute machine.

You can obtain this from the AWS console, from the command line using aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,PrivateIpAddress,Tags]' or from the output that was displayed on screen when you ran deploy-compute-target.

Add the instance-id to the following command to upgrade the version of the metadata instance

aws ec2 modify-instance-metadata-options --http-endpoint enabled --http-token required --instance-id <INSTANCE-ID-HERE>

Once the command has completed, try performing the previous SSRF exercises via the web app and see the difference in output

IMDSV2 Practice

We will interact with the IMDSv2 on the target machine, by first setting a stable SSH connection.

1. Setup a stable SSH connection

After the upgrade is applied, you can use the following commands to work with the Instance Metadata Service. You need to be on the system to do this. You can use the reverse shell to perform this exercise (unstable), or add a public key to the compute-target-machine vm and then SSH from the attacker machine (stable).

On the reverse shell, to add a public key to the target EC2 instance, generate a public/private keypair and append to the /home/ubuntu/.ssh/authorized_keys file on the target machine.

  1. Open a new terminal on student machine and SSH to the attacker machine

  2. On the attacker machine, Generate a private/public ED25519 - ssh-keygen -t ed25519 -C "" -f /tmp/ssh.key

  3. Restrict access to the key - chmod 400 /tmp/ssh.key

  4. Copy the contents of the public key by reading it cat /tmp/ssh.key.pub

  5. In the other terminal window, in the reverse shell paste the key in this echo command - echo "CONTENTS-OF-PUBLIC-KEY" >> /home/ubuntu/.ssh/authorized_keys

  6. From the attacker machine, SSH to the target machine using ssh -i /tmp/ssh.key ubuntu@10.0.100.11

2. Interacting with the IMDSv2

Generate a token using the following command

curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" "http://169.254.169.254/latest/api/token"

Pass the token in the following command

curl -H "X-aws-ec2-metadata-token:TOKEN-HERE" -v "http://169.254.169.254/latest/meta-data"

Additional references

Last updated