articleDec 31, 2021
Cloud Vulnerability Lab 6 (CloudGoat: EC2 SSRF)
CloudGoat EC2 SSRF path: Solus reads Lambda env keys for Wrex, SSRF hits IMDS, S3 yields Shepard admin creds, then invoke the target Lambda.
Cloud vulnerability analysis 6
[Scenario 5]: EC2 SSRF
Size: Medium
Difficulty: Moderate
Command: $ ./cloudgoat.py create ec2_ssrfScenario overview
Resources
- VPC (EC2)
- Lambda function
- One S3 bucket
Vulnerabilities
- Solus IAM user
- Read-only Lambda permissions
- Wrex access keys hard-coded in Lambda environment variables
- Hard-coded sensitive data
- Web app SSRF that reaches the AWS metadata API for another set of credentials
- Admin credentials stored in an S3 bucket
Goal
- Invoke
cg-lambda-/cloud goat id/. - Start as Solus, discover Lambda read access, and get steered toward an EC2 instance running an SSRF-prone web app.
- Abuse the app, pull keys from the EC2 metadata service, then obtain the credential that can invoke the Lambda and finish the scenario.
Exploit flow

Lab setup

Scenario path
- With the Solus IAM account, map the environment and find Lambda functions listed for the account.
- Inside a Lambda function, recover AWS access keys that belong to IAM user Wrex.
- Acting as Wrex, find an EC2 instance running a web app vulnerable to SSRF.
- Trigger SSRF through the
urlquery parameter on a GET request and steal AWS keys from the EC2 metadata service. - With the EC2 role keys, find a private S3 bucket that holds higher-privilege Shepard credentials.
- As Shepard with full privilege, invoke the original Lambda and complete the scenario.
IAM : Solus (Read Only Key Access)
Lambda function list -> Secret key
Wrex <-Exploit walkthrough
Read Solus's read-only key material

- While reviewing the lab,
start.txthanded over AWS credentials in read-only form. - I enumerated IAM with those credentials to see which AWS actions were actually available.

- The listing showed a Lambda vector worth chasing.
Inspect Lambda environment variables

- Through Pacu, calling into the
cg-lambda-idLambda surfaced env valuesEC2_ACCESS_KEY_IDandSECRET_KEY_ID.
[+] Secret (ENV): EC2_ACCESS_KEY_ID= <ACCESS_KEY>
[+] Secret (ENV): EC2_SECRET_KEY_ID= <ACCESS_SECRET_KEY>- The target Lambda exists in the account, and hard-coded env vars mean real AWS security credentials are sitting there.

- Solus lacks
lambda:InvokeFunction, so a direct invoke fails.

List and analyze Lambda further
- With the leaked Lambda env credentials, Pacu's
run aws__enum_accountshowed they belong to IAM userwrex. - From Wrex I listed which services that identity can touch.

- Wrex had more services than expected. Next check: running EC2 instances.

- I pulled EC2 inventory across regions, then used AWS query filters to cut the noise.

- Instance state and attached services were visible, but outside the known instance it was still hard to pin down the exact service.
Find the web service on EC2
- To get a clearer picture I started looking at which instance was actually serving something.

- The security group attached to the instance showed a web service in play.

- I grabbed the public IP to reach the host.

- Port 80 was serving a web app. A Node.js error said the
URLparameter was null rather than a string, so I fed it a string value next.


SSRF and IMDS credential theft
- To test SSRF I passed a link address and watched the response.

- The response leaked instance environment details.
- The app is SSRF-vulnerable and runs on EC2, so IMDSv1 can hand over the instance role credentials.

cg-ec2-role-ec2_ssrf_cgid84kpkl3ssy- That yields the security-credential path.

{ "Code" : "Success",
"LastUpdated" : "2021-08-13T12:26:30Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "<ACCESS_KEY>",
"SecretAccessKey" : "<ACCESS_SECRET_KEY>",
"Token" : "<ACCESS_SESSION_KEY>",
"Expiration" : "2021-08-13T18:44:43Z" }- Role credentials work like other IAM credentials, with one catch: a short-lived session token. I added a new AWS CLI profile that includes the token.


- Enumerating with the stolen role credentials showed
s3.list_bucketsworks.
Pull S3 data, extract credentials, invoke Lambda
- With S3 available I downloaded bucket contents through Pacu.


- The download contained another AWS credential set. Same playbook: new profile.

get-caller-identityshowed which user the keys belong to.

- The principal was
shepard. Next I mapped attached policies.

- Permissions on
shepard-ec2_ssrf_cgid84kpkl3ssyset the next move.

- As expected, Shepard had admin on the account. With those credentials I invoked
cg-lambda-ec2_ssrf_cgid84kpkl3ssy.
