abuse aws metadata service by using ssrf vulnerability

Posted by trammel at 2020-04-16

I recently worked on a small toy project to execute untrusted Python code in the docker container. I tested several online code execution engines to see how they responded to various attacks. In doing so, I found several interesting vulnerabilities in the code execution engine developed by qualified, which have been widely used, including websites such as codewars or interviewcake. The combination of being able to run code and network access and the infrastructure running in Amazon Web services allow me to show some very interesting vulnerabilities in this article.

Let's start with a few vulnerabilities I found in the qualified code execution engine through the interviewcake client. Then, we will discuss a specific security issue: SSRF vulnerability in services running on AWS. I won't talk about SSRF vulnerabilities and related basic knowledge, because there are many related resources (can be found here, here and here). In a word, it's a vulnerability that allows you to let applications initiate network connections.

Note 1: in the context of the online code execution engine, it is debatable whether the term SSRF is appropriate because it allows meaningful network connections. However, I chose to stick to the term because the vulnerability I demonstrated applies to any application running on AWS that is vulnerable to SSRF attacks.

Note 2: even if I'm talking about interviewcake in this article, I want to say that they don't have any security issues, and the one I find doesn't represent any security risks.

Vulnerability description

If you browse interviewcake's random questions page, you will find a small area at the bottom of the page where you can type and execute code.

We can follow Python code and run any bash command:

Through further mining, we can see that the host name changes every time it runs. The init process runs in the following control groups:

Based on these two information, the code seems likely to be running in the docker container. The container seems to be able to access the Internet, so we can easily check out what the container's Internet IP is, such as using the very convenient service.

If we do reverse DNS lookup, we can see that the IP belongs to AWS EC2:

For those unfamiliar with EC2, this is a digital ocean like service that allows you to generate a virtual machine in the cloud.

Loophole utilization

AWS EC2 has a feature called the instance metadata service. This function enables any EC2 instance to access the rest API running on, which returns data about the instance itself. Some sample data includes instance names, instance image (AMI) IDS, and other interesting things.

Because our code seems to run on the EC2 instance (or more specifically, in the docker container of the EC2 instance), this API can be accessed. Let's see what we can get out of it.

We get the following output:

Let's break up the above.


This is the identifier AMI (Amazon machine image) used by the host. It looks like it's a private ID, but it doesn't make any very exciting sense.

Security Credential

This is a list of Iam roles attached to the machine. Iam (identity access management) is an AWS service that allows you to manage users, roles, and permissions. We see that here it is a single role - ECS instance role, so you can use the metadata API to access the credential data attached to this role. This is a mechanism that allows you to attach roles to machines, rather than hardcode AWS API keys into application code. We can query API to get related voucher data:

With these credentials, an application (or attacker) can use the AWS API to perform any action allowed by the role ecsinstancerole. ECS represents EC2 container service. It's another AWS service that allows you to easily run the docker container in the cloud and extract the machines and ways it runs.

Now, we're obviously interested in knowing the level of access these credentials can provide us. If we dig AWS documents, we can easily find that ecsinstancerole is a default Iam role, with the following policies:

Therefore, we can do some interesting things, including creating an ECS cluster, deleting EC2 instances from the cluster, and writing application logs.

User script

This endpoint returns a user-defined script that runs the first time a new EC2 instance is started. This script is often used for basic configurations, such as updating packages, running services, and obviously sometimes for storing sensitive information (even if this is not encouraged).

I have copied and pasted the following interesting content in the script:

The last line reveals a newrelic license key.

The first command downloads the configuration file from ECS conf S3. Using the AWS cli tool, we noticed that the file ecs.config was publicly accessible even if the stored content could not be listed.

The auth parameter is a base-64 encoded string, decoded to codesearchdeploy: somepassword (the password has been edited), which allows us to log in to the qualified private docker!

This means that we can retrieve the docker image codewares / Runner server to see what's in it, including a backdoor or any malware in it, and push it back to the registry. Then, our malicious code will run at the execution time of quality's code execution engine, which means that every time someone submits a solution on interviewcake, they will encounter problems such as codewars.


I reported the problem to Jack, and then the leak was fixed in a few days.

When you run an application on AWS, you have to understand the metadata API, because any SSRF in your application has huge consequences. To limit this, it is best to follow these principles.

1. Do not store any sensitive data in the configuration script (AWS is called user script).

2. If your machine needs to attach an Iam role, please give it the absolute minimum permission. You can use the Iam policy emulator to ensure that a set of permissions you set behave as you expect.

3. If you do not use metadata API, please block it with firewall or only allow root user access (for example, use iptables).

If you want to learn more about this topic, see additional resources:

1. AWS vulnerability and attacker's perspective, by rhinolabs

2. EC2 most dangerous function