AWS Penetration Testing: Cloud Security Testing Methodology

AWS penetration testing is substantially different from traditional network or web application testing. The attack surface is distributed, most "network" access happens over HTTPS to AWS API endpoints, and the highest-impact misconfigurations live in IAM policies, resource permissions, and service-to-service trust relationships — not in open ports or missing patches.

AWS permits authorized security testing of your own infrastructure without prior approval for most services. Some services still require notification. Always confirm the current policy in the AWS Customer Support Policy for Penetration Testing before beginning.

What You're Testing in AWS

AWS environments typically have several distinct attack surfaces:

  • IAM — overly permissive policies, privilege escalation paths, cross-account trust
  • S3 — public bucket access, bucket ACLs, object-level permissions
  • EC2 — instance metadata service (IMDS), security group misconfigurations, publicly exposed instances
  • Lambda — function permissions, environment variable exposure, event source injection
  • RDS / DynamoDB — public accessibility, snapshot exposure, encryption at rest
  • CloudFormation / Terraform state — hard-coded secrets in infrastructure code
  • Secrets Manager / SSM Parameter Store — over-broad access to secrets

Reconnaissance: External Footprinting

S3 Bucket Enumeration

Public S3 buckets have caused some of the largest data breaches in cloud history. Start by finding buckets associated with the target organization.

# Enumerate S3 buckets by common naming patterns
# (replace "target" with the company name / brand)
aws s3 ls s3://target --no-sign-request
aws s3 ls s3://target-dev --no-sign-request
aws s3 ls s3://target-backup --no-sign-request
aws s3 ls s3://target-prod --no-sign-request
aws s3 ls s3://target-assets --no-sign-request
aws s3 ls s3://target-logs --no-sign-request

# Use tools like s3scanner or cloud_enum for systematic enumeration
python3 cloud_enum.py -k target --disable-azure --disable-gcp

# s3scanner
s3scanner --bucket-file bucket-names.txt

Also check:

  • JavaScript files on the web application that reference S3 bucket URLs
  • CloudFront distributions backed by S3 (the bucket name may be in the origin header)
  • Error messages from the application that reveal internal bucket names

AWS Account and Resource Discovery

# If you have any AWS credentials (e.g., found in source code or env vars):
aws sts get-caller-identity

# Enumerate accessible regions
aws ec2 describe-regions --all-regions

# Find publicly exposed resources
aws ec2 describe-instances --filters "Name=ip-address,Values=*" 2>/dev/null
aws rds describe-db-instances 2>/dev/null | jq '.DBInstances[] | {id:.DBInstanceIdentifier, public:.PubliclyAccessible}'

IAM Analysis

IAM is the most complex and highest-impact area of AWS security. The goal is to find privilege escalation paths — ways to move from low-privilege access to higher access, ideally AdministratorAccess.

Enumerate Your Current Permissions

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

# What can I do? (enumerate policies attached to current identity)
aws iam list-attached-user-policies --user-name $(aws sts get-caller-identity --query Arn --output text | cut -d'/' -f2)
aws iam list-user-policies --user-name $(aws iam get-user --query 'User.UserName' --output text)
aws iam list-groups-for-user --user-name $(aws iam get-user --query 'User.UserName' --output text)

# Retrieve policy documents
aws iam get-policy-version --policy-arn  --version-id v1

Common IAM Privilege Escalation Paths

Several well-documented IAM privilege escalation paths let a low-privilege user reach admin. The most common:

Permissions Held Escalation Path
iam:CreatePolicyVersion Create a new policy version with AdministratorAccess and set it as default
iam:AttachUserPolicy Attach AdministratorAccess to your own user
iam:CreateLoginProfile Create console access for an existing high-privilege user
iam:PassRole + ec2:RunInstances Launch an EC2 instance with an admin role attached, then access via IMDS
iam:PassRole + lambda:CreateFunction Create a Lambda with an admin role and invoke it to exfiltrate credentials
sts:AssumeRole Assume a role with broader permissions than current identity
cloudformation:CreateStack + iam:PassRole Deploy a stack that creates admin resources using a passed role

Use Pacu or cloudMapper to automatically identify escalation paths:

# Pacu — AWS exploitation framework (Kali Linux / pip)
python3 pacu.py

# In Pacu, enumerate IAM:
run iam__enum_permissions
run iam__privesc_scan

# Or use enumerate-iam for quick permission discovery
python3 enumerate-iam.py --access-key AKIA... --secret-key ...

EC2 Instance Metadata Service (IMDS) Attacks

If your web application has a Server-Side Request Forgery (SSRF) vulnerability and runs on EC2, you can use it to retrieve the instance's IAM role credentials from the metadata service.

IMDS v1 (No Authentication — Legacy)

# From SSRF on the web application:
# Retrieve IAM role name:
http://169.254.169.254/latest/meta-data/iam/security-credentials/

# Retrieve credentials for that role:
http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE-NAME

# Response:
{
  "Code": "Success",
  "LastUpdated": "2026-06-27T10:00:00Z",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIA...",
  "SecretAccessKey": "...",
  "Token": "...",
  "Expiration": "2026-06-27T16:00:00Z"
}

With these credentials, you can call AWS APIs with the EC2 instance's role permissions.

IMDS v2 (Requires Session Token)

IMDS v2 requires a PUT request with a TTL header to get a session token first, then uses that token in the GET:

# Step 1: Get session token (TTL in seconds, max 21600)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Step 2: Use token to query metadata
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/

If the application is vulnerable to SSRF but uses IMDSv2, you need an SSRF that supports custom headers or a two-request chain — more complex but still possible in some architectures.

Lambda Function Security Testing

Environment Variable Exposure

Lambda functions frequently store secrets (database passwords, API keys, encryption keys) in environment variables. If you have read access to Lambda configuration:

# List all Lambda functions
aws lambda list-functions --query 'Functions[*].[FunctionName,Runtime,Role]' --output table

# Get environment variables for a specific function
aws lambda get-function-configuration --function-name target-function \
  --query 'Environment.Variables'

Event Source Injection

If a Lambda function processes untrusted input from SQS, SNS, S3 events, or API Gateway without validation, the event data itself can be a vector for injection. Test for SQL injection, command injection, and SSTI in Lambda event handlers the same way as any other endpoint — the entry point is just different.

Secrets in Source Code and Infrastructure

AWS credentials frequently leak into public repositories, S3 buckets, and infrastructure code. Look for:

# Scan a git repo for AWS credentials
trufflehog git https://github.com/target/repo --only-verified

# Or grep for patterns
grep -rn "AKIA[0-9A-Z]{16}" .    # Access key IDs
grep -rn "aws_secret_access_key" .
grep -rn "aws_access_key_id" .

# Check CloudFormation templates for hard-coded secrets
grep -rn "NoEcho: false" . | grep -i "password\|secret\|key"

# Check Terraform state files (often contain sensitive outputs)
cat terraform.tfstate | jq '.resources[].instances[].attributes | to_entries[] | select(.value | type == "string" and test("password|secret|key"; "i"))'

S3 Permission Testing

# Test for public list access
aws s3 ls s3://target-bucket --no-sign-request

# Test for public read access on objects
aws s3 cp s3://target-bucket/sensitive.txt /tmp/ --no-sign-request

# Test for public write access
aws s3 cp /tmp/test.txt s3://target-bucket/test.txt --no-sign-request

# Check bucket ACL (if you have credentials with s3:GetBucketAcl)
aws s3api get-bucket-acl --bucket target-bucket

# Check bucket policy
aws s3api get-bucket-policy --bucket target-bucket

# List all buckets and their public access blocks
aws s3api list-buckets --query 'Buckets[*].Name' --output text | \
  xargs -I{} aws s3api get-public-access-block --bucket {} 2>/dev/null

Key Tools for AWS Penetration Testing

Tool Purpose
Pacu AWS exploitation framework — IAM enumeration, privilege escalation, post-exploitation
ScoutSuite Multi-cloud security auditing — comprehensive misconfiguration reporting
Prowler AWS security best practices auditing (CIS Benchmark, SOC 2, PCI DSS)
cloudmapper Network diagram and attack surface visualization for AWS
enumerate-iam Brute-force IAM permissions for a given credential set
trufflehog Secret scanning in git repos, S3, and more
s3scanner Enumerate and check public access on S3 buckets
cloud_enum Multi-cloud resource enumeration via naming patterns

Rules of Engagement for AWS Testing

AWS testing has specific operational constraints. Before starting:

  • Get written authorization from the account owner — not just verbal approval from a developer. The statement should name the specific AWS account IDs in scope.
  • Review AWS's penetration testing policy — some services (Route 53, CloudFront, WAF) require prior notification; DDoS simulation is always prohibited.
  • Avoid production disruption — avoid actions that terminate running instances, delete data, or incur significant unexpected charges.
  • Document everything — AWS logs all API calls in CloudTrail. Your testing activity is visible. Document your work so it can be distinguished from real attacker activity during incident response review.
  • Use isolated test accounts when possible — testing with production credentials against production resources carries real risk of impact.

Ironimo scans the web application layer of AWS-hosted environments using the same Kali Linux tooling professional pentesters use — SSRF testing that reaches IMDS endpoints, API endpoint discovery, authentication bypass, and injection testing across your application's attack surface.

Combine automated scanning with your manual AWS infrastructure review for full coverage across both layers.

Start free scan
← Back to blog