Cloud security

CloudGoat walkthrough series: EC2 server-side request forgery (SSRF)

February 3, 2021 by Mosimilolu Odusanya

This is the fifth in the walkthrough series of the CloudGoat scenarios. CloudGoat is a “vulnerable by design” AWS deployment tool designed by Rhino Security Labs. It is used to deploy a vulnerable set of AWS resources and is designed to teach and test cloud security penetration testing via issues commonly seen in real-life environments.

This walkthrough assumes you have CloudGoat setup on your Kali Linux. You can use our post on Working with CloudGoat: The “Vulnerable by Design” AWS Environment as a guide in deploying it.

Scenario summary

The scenario starts with an IAM user Solus. The attacker discovers they have ReadOnly permissions to a Lambda function, where hardcoded secrets lead them to an EC2 instance running a web application that is vulnerable to SSRF. After exploiting the vulnerable app and acquiring keys from the EC2 metadata service, the attacker gains access to a private S3 bucket with a set of keys that allow them to invoke the Lambda function and complete the scenario.

Goal: Invoke the Lambda function.


To deploy the resources for each scenario on AWS.

./ create ec2_ssrf

  1. Deploying the resources gives us the access key and secret key for Solus.
  2. Save the credential to a profile – Solus.

aws configure –profile Solus

  1. Perform reconnaissance on the user “Solus” to see what privileges the user has by enumerating the policies and permissions attached to the user.

We tried running the usual commands, such as “list-user-policies”, “list-attached-user-policies” and “list roles”, and we noticed we were not authorized to carry out those actions.

aws iam list-user-policies –-user-name <insert username here> –profile <insert profile name here>

list-user-policies: Lists the names of inline policies embedded in the specified IAM user.

aws iam list-attached-user-policies –-user-name <insert username here> –profile <insert profile name here>

list-attached-user-policies: Lists all managed policies that are attached to the specified IAM user.

aws iam list-roles –profile <insert profile name here>

list-roles: Lists the IAM roles that have the specified path prefix.

  1. Since we are unable to get more information about Solus, we perform a recon on the Lambda function.

aws lambda list-functions –region us-east-1 –profile <insert profile name here>

list-function: Returns a list of Lambda functions, with the version-specific configuration of each. Lambda returns up to 50 functions per call.

We notice that the Lambda function has an access key and a secret key stored in the environment variables. We want to find out more information about this Lambda function.

aws lambda get-function –function-name <insert function name here> –region us-east-1 –profile <insert profile name here>

get-function: Returns information about the function or function version, with a link to download the deployment package that’s valid for 10 minutes. If you specify a function version, only details that are specific to that version are returned.

This leads us to an S3 bucket. Accessing the S3 bucket via the link provided in the location variable downloads the source code for the Lambda function.

  1. Save the compromised credential from the Lambda function in another profile – Lambda_Solus.

aws configure –profile Lambda_Solus

  1. Perform a recon on the compromised credential.

We can assume it was assigned to a user “Wrex”. We tried running the usual commands: “list-user-policies”, “list-attached-user-policies” and “list-roles”. We were not authorized to carry out those actions.

  1. Get more information about the EC2 instance running.

aws ec2 describe-instances –region us-east-1 –profile <insert profile name here>

describe-instances: Describes the specified instances or all instances.

  1. Let’s visit the public IP address of the EC2 Instance, since it has port 80 enabled.

We immediately notice an error. Since we already know the scenario has to do with SSRF, we manipulate the server to make HTTP requests to an arbitrary domain (in our case, the localhost).

SSRF is a vulnerability that tricks the web applications into making HTTP requests on behalf of the bad actor to a URL. This allows the bad actor to gain access to sensitive information or data that are directly exposed or the bad actor does not have access to such as the AWS metadata, other web applications based within the organization’s infrastructure or external web services. In some cases, the bad actor is also able to perform arbitrary command execution.

We exploit this vulnerability by querying the instance metadata API to obtain the credentials to reveal the role name of the EC2 instance. The instance metadata contains data about the EC2 instance that you can use to configure or manage the running instance.

This returns the access key ID, secret access key and the session token of the IAM role attached to the EC2 instance. This credential is a temporary one, as it has an expiration date.

  1. Save the compromised credential from the instance metadata in another profile — ec2role. We do a bit of recon using our newly compromised credential. We use this credential to gather information about the S3 buckets.

aws s3 ls –profile <insert profile name here>

Accessing the S3 bucket reveals that it has an admin file stored with an access key and secret key ID.

  1. Save the compromised credential in another profile — AdminUser.

aws configure –profile AdminUser

  1. Perform a recon on the compromised credential.

We can assume it was assigned to a user named “Shepard”.

We tried running the usual commands — “list-attached-user-policies”, “list-user-policies” and “list-roles” — to gain more information about the permissions assigned to the user.

aws iam list-attached-user-policies –-user-name <insert username here> –profile <insert profile name here>

list-attached-user-policies: Lists all managed policies that are attached to the specified IAM user.

aws iam get-policy –policy-arn <insert the policy arn here>

aws iam get-policy-version –policy-arn <insert the policy arn here> –version-id <insert version id here>

We have full admin privileges with this credential.

  1. We invoke the function and see what happens.

aws lambda invoke –function-name <insert lambda function name here> ./<insert output file name here>.txt –region us-east-1 –profile <insert profile name here>

  1. To destroy the resources created during this lab:

./ destroy ec2_ssrf


In this scenario, we were able to exploit a number of misconfigurations and bad practices to gain access to the sensitive data.

  1. Credentials (access key and a secret key) were stored in the environment variables of a Lambda function.
  2. Due to the SSRF vulnerability on the web application, we were able to gain access to yet another set of credentials via the AWS metadata API.
  3. Admin credentials were also stored in an S3 bucket, which eventually gave us full privileges.



AWS CLI Command Reference – IAM, AWS

Well, that escalated quickly, Bishop Fox

AWS IAM Privilege Escalation Methods, Rhino Security Labs

Server Side Request Forgery, OWASP

Server-side request forgery (SSRF), PortSwigger

Posted: February 3, 2021
Mosimilolu Odusanya
View Profile

Mosimilolu (or 'Simi') works as a full-time cybersecurity consultant, specializing in privacy and infrastructure security. Outside of work, her passions includes watching anime and TV shows and travelling.