Why misconfiguration is consistently the #1 attack vector in modern infrastructure — and how AI accelerates both attack and defense.
Year after year, misconfiguration dominates breach statistics. It is not exotic zero-days that compromise organizations — it is default passwords, open buckets, and overly permissive policies.
| Source | Finding |
|---|---|
| OWASP Top 10 (2021) | Security Misconfiguration moved to #5, up from #6 |
| Verizon DBIR 2024 | 68% of breaches involved a human element — misconfig is the leading technical cause |
| IBM Cost of a Breach | Cloud misconfiguration avg. cost: $4.0M per incident |
| NSA/CISA Top 10 | Misconfigurations ranked #1 in joint advisory (2023) |
| Palo Alto Unit 42 | 80% of cloud exposures stem from misconfigs, not vulnerabilities |
None of these required a zero-day. Each was a configuration mistake that went undetected — sometimes for years.
Infrastructure misconfigurations span every layer of the stack. Attackers look for the weakest link across all of them simultaneously.
Public S3 buckets remain one of the most common cloud exposures. A single misconfigured ACL or bucket policy can expose terabytes of sensitive data.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::company-backups",
"arn:aws:s3:::company-backups/*"
]
}]
}
"Principal": "*" grants access to anyone on the internet. Combined with ListBucket, attackers can enumerate every object. The bucket name company-backups is also trivially guessable.
IAM policies that grant excessive permissions are the gateway to privilege escalation in cloud environments.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}]
}
This policy grants full administrator access to every resource in the AWS account. It is more common than you would expect.
Cloud instance metadata services (IMDS) provide credentials and configuration to running instances. When accessible via SSRF or misconfigured network policies, they become a goldmine.
# AWS IMDSv1 — no authentication required
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Response reveals the IAM role name
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/MyAppRole
# Returns temporary credentials:
# {
# "AccessKeyId": "ASIA...",
# "SecretAccessKey": "wJalr...",
# "Token": "IQoJb3...",
# "Expiration": "2026-04-09T18:00:00Z"
# }
| Provider | Endpoint |
|---|---|
| AWS | 169.254.169.254/latest/meta-data/ |
| GCP | metadata.google.internal/computeMetadata/v1/ |
| Azure | 169.254.169.254/metadata/instance?api-version=2021-02-01 |
| DigitalOcean | 169.254.169.254/metadata/v1/ |
AWS IMDSv2 requires a PUT request to obtain a session token first, blocking most SSRF attacks. However, many organizations still allow IMDSv1 fallback.
Kubernetes RBAC is powerful but frequently misconfigured. Overly broad ClusterRoleBindings are the most common issue.
# DANGEROUS: Grants cluster-admin to all service accounts
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: permissive-binding
subjects:
- kind: Group
name: system:serviceaccounts
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
Every pod in every namespace now has full cluster-admin privileges. A single compromised container can read all secrets, create privileged pods, and take over the entire cluster.
verbs: ["*"] on resources: ["*"]The Kubernetes Dashboard, when exposed without authentication, provides full cluster management via a web UI. Tesla's 2018 breach started with an unauthenticated dashboard.
# Dashboard exposed via LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: LoadBalancer # PUBLIC!
ports:
- port: 443
targetPort: 8443
A privileged pod has full access to the host node, effectively breaking out of the container sandbox.
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
spec:
hostNetwork: true
hostPID: true
containers:
- name: shell
image: ubuntu
securityContext:
privileged: true
volumeMounts:
- name: host-fs
mountPath: /host
volumes:
- name: host-fs
hostPath:
path: /
With privileged: true, hostPID, hostNetwork, and the host filesystem mounted, this pod has complete control over the node.
Storing secrets as environment variables is a common anti-pattern. Environment variables are visible in process listings, logged by crash reporters, and exposed via the Kubernetes API.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
spec:
template:
spec:
containers:
- name: api
image: myapp:latest
env:
- name: DB_PASSWORD
value: "SuperSecret123!" # Hardcoded!
- name: AWS_SECRET_ACCESS_KEY
value: "wJalrXUtnFEMI/K7MDENG" # AWS creds in plain text!
- name: JWT_SIGNING_KEY
value: "my-jwt-secret-key" # JWT secret exposed!
kubectl get pod api-server -o yaml exposes all env vars/proc/<pid>/environ on the nodeUse Kubernetes Secrets (with encryption at rest), or external secret managers (Vault, AWS Secrets Manager) via CSI driver or operator.
By default, Docker containers run as root. If an attacker escapes the container or exploits a volume mount, they get root on the host.
# BAD: Running as root (default)
FROM python:3.11
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
# Container process runs as UID 0 (root)!
# BETTER: Non-root user
FROM python:3.11
RUN groupadd -r appuser && useradd -r -g appuser appuser
COPY --chown=appuser:appuser . /app
WORKDIR /app
RUN pip install -r requirements.txt
USER appuser
CMD ["python", "app.py"]
# docker-compose.yml — NEVER do this
services:
monitoring:
image: monitoring-tool
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Full Docker API access!
Mounting the Docker socket gives the container full control over the Docker daemon — it can create privileged containers, access host filesystem, and effectively own the host.
version: "3.8"
services:
webapp:
image: node:14 # EOL version with known CVEs
ports:
- "0.0.0.0:3000:3000" # Bound to all interfaces
environment:
- NODE_ENV=development # Debug mode in production
- DATABASE_URL=postgres://admin:password123@db:5432/app
privileged: true # Unnecessary privilege
network_mode: host # No network isolation
db:
image: postgres:12
environment:
- POSTGRES_PASSWORD=password123 # Weak password
ports:
- "0.0.0.0:5432:5432" # Database exposed to internet
volumes:
- /data:/var/lib/postgresql/data # No encryption
Default credentials on network devices, management interfaces, and services remain shockingly common even in enterprise environments.
| Device / Service | Default Username | Default Password |
|---|---|---|
| Cisco IOS | admin | admin / cisco |
| Tomcat Manager | tomcat | tomcat / s3cret |
| Jenkins | (no auth) | (open by default) |
| MongoDB | (no auth) | (binds 0.0.0.0 by default) |
| Redis | (no auth) | (no password by default) |
| Elasticsearch | (no auth) | (open by default <v8) |
| IPMI/BMC | ADMIN | ADMIN |
# Default SNMP community strings allow reading device configs
snmpwalk -v2c -c public 10.0.0.1 system
snmpwalk -v2c -c private 10.0.0.1 # "private" = read-write access
# Common default community strings:
# public, private, community, manager, cisco, cable-docsis
Management interfaces exposed to the internet provide direct access to administer critical infrastructure.
| Port | Service | Risk |
|---|---|---|
| 22 | SSH | Brute force, key auth bypass |
| 23 | Telnet | Cleartext credentials |
| 161/162 | SNMP | Device enumeration, config read |
| 445 | SMB | EternalBlue, relay attacks |
| 623 | IPMI | BMC takeover, hash disclosure |
| 2379 | etcd | K8s secrets, cluster state |
| 5900 | VNC | Often weak/no auth |
| 6443 | K8s API | Cluster takeover |
| 8080 | HTTP Alt | Admin panels, debug endpoints |
| 9090 | Prometheus | Metrics, internal topology |
| 10250 | Kubelet | Pod exec, node takeover |
Attackers scan for these ports using masscan/nmap, then fingerprint services to identify default or weak configurations before attempting exploitation.
LLMs excel at configuration auditing because they can understand the semantic intent of configurations, not just pattern-match known-bad values.
Terraform files define infrastructure-as-code. Misconfigurations here propagate to every deployment.
# main.tf — Spot the issues
resource "aws_security_group" "web_sg" {
name = "web-server-sg"
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # All ports open to internet!
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.large"
iam_instance_profile = aws_iam_instance_profile.admin.name
associate_public_ip_address = true
metadata_options {
http_endpoint = "enabled"
http_tokens = "optional" # IMDSv1 still allowed!
}
user_data = <<-EOF
#!/bin/bash
echo "DB_PASS=Pr0duction_S3cret!" >> /etc/environment
EOF
}
resource "aws_db_instance" "main" {
engine = "mysql"
instance_class = "db.t3.medium"
publicly_accessible = true # RDS on the internet!
storage_encrypted = false # No encryption at rest!
skip_final_snapshot = true
password = "admin123" # Weak hardcoded password!
}
You are a cloud security auditor. Analyze the following Terraform
configuration for security misconfigurations. For each finding:
1. Severity (CRITICAL / HIGH / MEDIUM / LOW)
2. Resource affected
3. The specific misconfiguration
4. Attack scenario — how an attacker would exploit this
5. Remediation — the exact Terraform change needed
Also identify any cross-resource attack chains where multiple
misconfigurations combine to create a more severe vulnerability.
Rate the overall infrastructure security posture on a scale of 1-10.
--- BEGIN TERRAFORM ---
[paste configuration here]
--- END TERRAFORM ---
CRITICAL — Attack Chain Identified: The security group allows all inbound traffic + IMDSv1 is enabled + admin IAM profile attached = SSRF to full AWS account compromise. An attacker who finds any web vulnerability can reach the metadata endpoint, steal admin credentials, and pivot to all AWS resources including the unencrypted, publicly accessible RDS database.
# deployment.yaml — Production API server
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-api
namespace: default # Using default namespace
spec:
replicas: 1 # Single replica for payment service?
template:
metadata:
labels:
app: payment-api
spec:
serviceAccountName: "" # Uses default SA
automountServiceAccountToken: true
containers:
- name: api
image: payment-api:latest # Mutable tag
securityContext:
runAsUser: 0 # Running as root
allowPrivilegeEscalation: true
ports:
- containerPort: 8080
env:
- name: STRIPE_SECRET_KEY
value: "sk_live_4eC39HqLyjWDarjtT1zdp7dc"
- name: DB_CONNECTION
value: "mysql://root:prod_pass@mysql:3306/payments"
resources: {} # No resource limits (DoS risk)
---
apiVersion: v1
kind: Service
metadata:
name: payment-api
spec:
type: LoadBalancer # Directly exposed
ports:
- port: 8080
A payment service with root execution, hardcoded Stripe keys, no resource limits, mutable image tags, and direct internet exposure.
# nginx.conf — Misconfigured reverse proxy
server {
listen 80;
server_name api.example.com;
# Missing: return 301 https://$host$request_uri;
location / {
proxy_pass http://backend:3000;
proxy_set_header X-Forwarded-For $remote_addr;
}
# Debug endpoint left in production
location /debug {
proxy_pass http://backend:3000;
# No access restriction!
}
# Server status exposed
location /nginx_status {
stub_status on;
# No access restriction!
}
# Path traversal via alias misconfiguration
location /static {
alias /var/www/static/; # Trailing slash mismatch
}
# /static../etc/passwd could work!
# Version disclosure
server_tokens on;
# Missing security headers:
# X-Frame-Options, X-Content-Type-Options,
# Content-Security-Policy, Strict-Transport-Security
}
/static../etc/passwd path traversalserver_tokens onCombine traditional scanning tools with AI analysis for comprehensive coverage. The AI layer interprets raw scan output, eliminates false positives, and identifies attack chains.
import anthropic
import subprocess
import json
def ai_scan_pipeline(target_configs: dict) -> str:
"""Run scanners, then feed results to AI for analysis."""
# Step 1: Run traditional scanners
results = {}
results["trivy"] = subprocess.run(
["trivy", "config", "--format", "json", "./"],
capture_output=True, text=True
).stdout
results["kube_bench"] = subprocess.run(
["kube-bench", "run", "--json"],
capture_output=True, text=True
).stdout
# Step 2: Feed to AI for correlation
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
messages=[{
"role": "user",
"content": f"""Analyze these infrastructure scan results.
Identify the top 5 most critical findings and any attack chains
where multiple issues combine for greater impact.
Scanner Results: {json.dumps(results)}
Config Files: {json.dumps(target_configs)}
Provide a prioritized remediation plan."""
}]
)
return response.content[0].text
ScoutSuite is an open-source multi-cloud security auditing tool that collects configuration data using cloud provider APIs and highlights risk areas.
# Install
pip install scoutsuite
# Run against AWS account
scout aws --profile my-profile
# Run against GCP project
scout gcp --user-account --project-id my-project
# Run against Azure subscription
scout azure --cli
Prowler performs security assessments against CIS benchmarks and custom checks for cloud environments.
# Install Prowler
pip install prowler
# Run all checks against AWS
prowler aws
# Run specific check categories
prowler aws --category internet-exposed
prowler aws --service iam s3 ec2
# Output as JSON for AI processing
prowler aws --output-formats json -o ./prowler-results/
prompt = f"""You are analyzing Prowler security scan results for an AWS account.
Prowler found {len(findings)} issues:
- CRITICAL: {critical_count}
- HIGH: {high_count}
- MEDIUM: {medium_count}
For each CRITICAL finding, explain:
1. What the misconfiguration is
2. The realistic attack scenario
3. Immediate remediation steps (AWS CLI commands)
4. How this finding relates to other findings (attack chains)
Findings: {json.dumps(critical_findings)}"""
kube-bench checks Kubernetes clusters against the CIS Kubernetes Benchmark — the industry standard for K8s hardening.
# Run kube-bench on a cluster node
kube-bench run --targets master,node,policies
# Output as JSON for AI consumption
kube-bench run --json > kube-bench-results.json
# Run specific checks
kube-bench run --check 1.2.1,1.2.2,4.2.1
| Section | Focus | Example Check |
|---|---|---|
| 1.x | Control Plane | API server anonymous auth disabled |
| 2.x | etcd | Client certificate auth enabled |
| 3.x | Control Plane Config | Controller manager bind address |
| 4.x | Worker Nodes | Kubelet authentication |
| 5.x | Policies | Pod Security Standards enforced |
Feed kube-bench JSON output to Claude to get plain-English explanations of each failing check, specific kubectl commands to remediate, and identification of which failures create compound risks.
Trivy scans container images, filesystems, IaC files, and Kubernetes clusters for vulnerabilities, misconfigurations, and exposed secrets.
# Scan a container image for vulnerabilities
trivy image nginx:latest
# Scan Terraform/Kubernetes configs for misconfigurations
trivy config ./infrastructure/
# Scan a running Kubernetes cluster
trivy k8s --report summary cluster
# Scan filesystem for secrets
trivy fs --scanners secret ./
# JSON output for AI pipeline
trivy config --format json ./infrastructure/ > trivy-results.json
A complete AI-augmented infrastructure audit combines multiple scanners into a unified analysis pipeline.
import anthropic, json, subprocess
from pathlib import Path
class InfraAuditor:
def __init__(self):
self.client = anthropic.Anthropic()
self.findings = {}
def collect_configs(self, path: str):
"""Gather all configuration files."""
config_patterns = [
"**/*.tf", "**/*.yaml", "**/*.yml",
"**/Dockerfile", "**/docker-compose*.yml",
"**/nginx.conf", "**/.env*"
]
configs = {}
for pattern in config_patterns:
for f in Path(path).glob(pattern):
configs[str(f)] = f.read_text()
return configs
def run_scanners(self, path: str):
"""Run all available scanners."""
scanners = {
"trivy": f"trivy config --format json {path}",
"checkov": f"checkov -d {path} -o json",
}
for name, cmd in scanners.items():
result = subprocess.run(
cmd.split(), capture_output=True, text=True
)
self.findings[name] = result.stdout
def ai_analyze(self, configs: dict) -> str:
"""AI correlation and analysis."""
msg = self.client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=8192,
messages=[{
"role": "user",
"content": f"""As a senior penetration tester, analyze this
infrastructure for security weaknesses.
CONFIGS: {json.dumps(configs, indent=2)}
SCANNER OUTPUT: {json.dumps(self.findings, indent=2)}
Produce:
1. Critical attack chains (multi-step paths)
2. Prioritized findings with CVSS-like scoring
3. Specific remediation for each finding
4. Overall risk assessment"""
}]
)
return response.content[0].text
AI can assist in interpreting enumeration results, identifying patterns, and suggesting next steps during infrastructure reconnaissance.
def ai_enumerate(scan_output: str) -> str:
"""Use AI to analyze nmap/masscan output and plan next steps."""
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
messages=[{
"role": "user",
"content": f"""Analyze this network scan output from a
sanctioned penetration test. Identify:
1. All services and their versions
2. Services likely running with default configs
3. Potential misconfigurations based on port/service combos
4. Suggested next enumeration steps for each service
5. Priority order for investigation
Scan output:
{scan_output}"""
}]
)
return response.content[0].text
| Tool | Scope | Best For | AI Integration |
|---|---|---|---|
| ScoutSuite | AWS, GCP, Azure | Multi-cloud posture assessment | JSON report parsing |
| Prowler | AWS, GCP, Azure | CIS benchmark compliance | JSON finding analysis |
| kube-bench | Kubernetes | CIS K8s benchmark | Remediation generation |
| Trivy | Images, IaC, FS | Vulnerability + misconfig scanning | CVE reachability analysis |
| Checkov | IaC files | Terraform/CloudFormation audit | Policy-as-code generation |
| tfsec | Terraform | Terraform-specific checks | HCL remediation |
| Falco | Runtime | Runtime anomaly detection | Alert triage + correlation |
Each tool produces raw findings. AI transforms those findings into actionable intelligence by correlating across tools, eliminating duplicates, identifying attack chains, and generating specific remediation commands.
Scenario: You have been given read access to a company's infrastructure configuration repository. Your mission: find all security weaknesses and map escalation paths.
terraform/main.tf — AWS infrastructure definitionk8s/deployment.yaml — Kubernetes workload configsk8s/rbac.yaml — RBAC policiesdocker/docker-compose.yml — Container orchestrationdocker/Dockerfile — Application container buildnginx/nginx.conf — Reverse proxy configurationci/pipeline.yml — CI/CD pipeline definitionThe best CTF submissions map complete attack chains across infrastructure layers.
/debug endpoint without auth, leaking internal service topologyPrompt: "Given these 7 configuration files, identify every possible
path from an external attacker to sensitive data exfiltration.
For each path, list the specific misconfigurations exploited at
each step and rate the overall difficulty (1-10)."
Infrastructure exploitation techniques are for authorized penetration testing and CTF competitions only. Unauthorized access to cloud resources or infrastructure is illegal.
Lesson 08 will build on infrastructure weaknesses to explore privilege escalation — moving from initial access to full control using the misconfigurations we identified today.