~/cloud/owasp-top-10-cloud-applications.md

OWASP Top 10 for Cloud Applications

4 min readApril 04, 2026by Gorav Singal#owasp#web-security#cloud-security
// TL;DR

The OWASP Top 10 still applies in the cloud — but the attack surface changes. Broken access control means misconfigured IAM, injection means Lambda event injection, and SSRF is the #1 cloud-specific risk. Learn the cloud twist on each vulnerability.

OWASP Top 10 for Cloud Applications

The OWASP Top 10 was written for traditional web applications. But in the cloud, the attack surface shifts. SQL injection becomes Lambda event injection. Broken access control becomes misconfigured IAM. And SSRF — barely a footnote in traditional web security — becomes the most dangerous cloud-specific attack vector.

This article maps each OWASP category to its cloud-native equivalent.

OWASP Top 10 in the Cloud Era

OWASP Cloud Attack Surface Mapping

A01: Broken Access Control

Traditional: User accesses another user’s data by changing an ID in the URL. Cloud twist: IAM misconfigurations, overly permissive S3 bucket policies, cross-account access without proper controls.

// ❌ S3 bucket policy — allows anyone to read
{
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::customer-data/*"
}

// ✅ Restricted to specific role
{
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::123456789:role/ApiServer"
  },
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::customer-data/*"
}

Cloud defenses: IAM least privilege, S3 Block Public Access, resource-based policies with explicit principals.

A02: Cryptographic Failures

Traditional: Transmitting sensitive data over HTTP, weak hashing. Cloud twist: Unencrypted S3 buckets, unencrypted RDS instances, KMS key mismanagement.

# Check all S3 buckets for encryption
aws s3api list-buckets --query 'Buckets[].Name' --output text | \
  xargs -I {} sh -c 'echo -n "{}: "; aws s3api get-bucket-encryption --bucket {} 2>/dev/null || echo "NOT ENCRYPTED"'

Cloud defenses: KMS encryption for all data at rest, TLS 1.2+ for all data in transit, SCPs enforcing encryption.

A03: Injection

Traditional: SQL injection via form inputs. Cloud twist: Lambda event injection — untrusted data arrives from SQS, S3 events, API Gateway, and other AWS services.

# ❌ Lambda event injection — S3 key used in shell command
import subprocess

def handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']
    # Attacker uploads file named: "; rm -rf / #"
    subprocess.run(f"process-file {bucket}/{key}", shell=True)  # INJECTION!

# ✅ Safe — use parameterized approach
def handler(event, context):
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']
    subprocess.run(["process-file", f"{bucket}/{key}"], shell=False)

Cloud defenses: Input validation on all event sources, parameterized commands, WAF on API Gateway.

A04: Insecure Design

Cloud twist: Architectures that don’t consider security boundaries — flat VPCs, shared service accounts, no network segmentation between microservices.

Cloud defenses: Threat modeling with STRIDE, network policies in Kubernetes, separate AWS accounts for prod/staging/dev.

A05: Security Misconfiguration

This is the #1 cloud vulnerability. More breaches happen from misconfiguration than from exploits.

# Common misconfigurations to check
# 1. Public security groups
aws ec2 describe-security-groups \
  --filters "Name=ip-permission.cidr,Values=0.0.0.0/0" \
  --query 'SecurityGroups[].{ID:GroupId,Name:GroupName}'

# 2. IMDSv1 enabled (allows SSRF credential theft)
aws ec2 describe-instances \
  --query 'Reservations[].Instances[?MetadataOptions.HttpTokens!=`required`].{ID:InstanceId,State:State.Name}'

# 3. Public RDS instances
aws rds describe-db-instances \
  --query 'DBInstances[?PubliclyAccessible==`true`].{ID:DBInstanceIdentifier}'

Cloud defenses: AWS Config rules, Checkov/tfsec on all Terraform, enforce IMDSv2, Security Hub enabled.

A06: Vulnerable and Outdated Components

Cloud twist: Vulnerable base images in Docker, outdated Lambda runtimes, unpatched AMIs.

Cloud defenses: Trivy image scanning, Dependabot auto-updates, ECR image scanning, Lambda runtime deprecation alerts.

A07: Identification and Authentication Failures

Cloud twist: Overly long-lived access keys, no MFA on IAM users, shared credentials between services, no token rotation.

# Find access keys older than 90 days
aws iam generate-credential-report
aws iam get-credential-report --query 'Content' --output text | \
  base64 -d | awk -F, 'NR>1 && $9!="N/A" && $11!="N/A" {print $1,$9}'

Cloud defenses: Enforce MFA, use IAM roles instead of access keys, rotate credentials automatically, short-lived tokens.

A08: Software and Data Integrity Failures

Cloud twist: Unsigned Docker images, unverified CI/CD artifacts, no provenance for deployed code.

Cloud defenses: cosign for image signing, SLSA provenance, Kubernetes admission controllers that verify signatures.

A09: Security Logging and Monitoring Failures

Cloud twist: CloudTrail not enabled in all regions, no VPC Flow Logs, no alerts on high-risk API calls.

Cloud defenses: Multi-region CloudTrail, CloudWatch alarms for security events, centralized SIEM, automated alerting.

A10: Server-Side Request Forgery (SSRF)

This is the most dangerous cloud-specific vulnerability. SSRF in a cloud environment gives attackers access to the Instance Metadata Service (IMDS) and temporary IAM credentials.

SSRF Cloud Attack Flow

# The classic SSRF attack in cloud
# Attacker sends: url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

# ❌ Vulnerable code — fetches any URL
import requests

def handler(event, context):
    url = event['queryStringParameters']['url']
    response = requests.get(url)  # SSRF!
    return {'statusCode': 200, 'body': response.text}

# ✅ Defended — allowlist + IMDSv2
import requests
from urllib.parse import urlparse

ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com']

def handler(event, context):
    url = event['queryStringParameters']['url']
    parsed = urlparse(url)

    if parsed.hostname not in ALLOWED_HOSTS:
        return {'statusCode': 403, 'body': 'Blocked'}
    if parsed.hostname.startswith('169.254.') or parsed.hostname == 'metadata.google.internal':
        return {'statusCode': 403, 'body': 'Blocked'}

    response = requests.get(url, timeout=5)
    return {'statusCode': 200, 'body': response.text}

Critical defense: Enforce IMDSv2 on all EC2 instances. IMDSv2 requires a session token that can’t be obtained via a simple GET request, effectively blocking most SSRF-based credential theft.

# Enforce IMDSv2 on all instances
aws ec2 modify-instance-metadata-options \
  --instance-id i-1234567890abcdef0 \
  --http-tokens required \
  --http-endpoint enabled

Cloud-Specific Mitigations Summary

OWASP Cloud Defense AWS Service
A01 IAM least privilege IAM Access Analyzer
A02 Encrypt everything KMS, ACM
A03 Validate all event inputs WAF, input validation
A05 Continuous compliance Config, Security Hub
A06 Scan everything ECR scanning, Trivy
A09 Log everything CloudTrail, VPC Flow Logs
A10 IMDSv2 + URL allowlists Instance metadata config

Key Takeaways

  1. SSRF is the #1 cloud risk — enforce IMDSv2 on every instance, no exceptions
  2. Misconfiguration > exploitation — most cloud breaches are misconfig, not zero-days
  3. Lambda event injection is real — treat all event sources as untrusted input
  4. IAM IS access control — broken IAM = broken access control in the cloud
  5. Encrypt by default — KMS for rest, TLS for transit, no exceptions
  6. Log everything, alert on anomalies — CloudTrail is your cloud security backbone

$ subscribe --weekly

One deep dive a week, in your inbox

System design, AI engineering, trading systems and interview prep. Tested code, real numbers. Free, and you can unsubscribe any time.

or read it on gyanbyte.substack.com

Share

Related Posts

Supply Chain Security — Protecting Your Software Pipeline

Supply Chain Security — Protecting Your Software Pipeline

In 2024, a single malicious contributor nearly compromised every Linux system on…

Security Ticketing and Incident Response

Security Ticketing and Incident Response

The worst time to figure out your incident response process is during an…

Security Mindset for Engineers — Think Like an Attacker

Security Mindset for Engineers — Think Like an Attacker

Most engineers think about security the way they think about flossing — they…

Secrets Management — Vault, SSM, and Secrets Manager

Secrets Management — Vault, SSM, and Secrets Manager

I’ve watched a production database get wiped because someone committed a root…

Penetration Testing Basics for Developers

Penetration Testing Basics for Developers

Most developers think of penetration testing as something a separate security…

Container Security — Docker and Kubernetes Hardening

Container Security — Docker and Kubernetes Hardening

Containers make deployment easy and security hard. That Dockerfile you copied…

Latest Posts

How to Stay Valuable as a Software Engineer in the AI Era: A Practical Playbook

How to Stay Valuable as a Software Engineer in the AI Era: A Practical Playbook

In the previous article I argued that AI is not killing software engineering…

How to Review AI-Generated Code: A Checklist for Catching What the Model Missed

How to Review AI-Generated Code: A Checklist for Catching What the Model Missed

A few months back I approved a PR that was almost entirely AI-generated. It…

How to Debug AI-Generated Code: Understand First, Fix Last

How to Debug AI-Generated Code: Understand First, Fix Last

In the last article I wrote about reviewing AI code before it goes in. This one…

The Future of Software Engineering: What AI Changes, What Stays, and Where the Jobs Go

The Future of Software Engineering: What AI Changes, What Stays, and Where the Jobs Go

Every few weeks somebody sends me a scary headline — “AI will replace all…

The Transactional Outbox Pattern: Never Lose an Event Again

The Transactional Outbox Pattern: Never Lose an Event Again

This is one of those patterns that looks like nothing until you get burnt once…

Event Sourcing, Explained: Store What Happened, Not Just the Final State

Event Sourcing, Explained: Store What Happened, Not Just the Final State

Here is a question I like to ask in interviews: your bank account shows a…