← Writeups

Teoria vs Practica Cloud Red Team

Teoría vs Práctica — Cloud Red Teaming (AWS / Azure / GCP)

Este documento conecta los conceptos teóricos de seguridad en cloud con lo que realmente hicimos en cada laboratorio. El objetivo es que entiendas por qué cada paso funciona y cómo se aplica la teoría en un entorno real.


Índice

  1. El Trío de la Explotación Cloud
  2. OSINT y Reconocimiento
  3. Fuga de Código Fuente (.git)
  4. SSRF + RCE — El Caballo de Troya Web
  5. Instance Metadata Service (IMDS)
  6. IAM / RBAC / Cloud IAM
  7. Storage Buckets
  8. APIs de Gestión Cloud
  9. Glosario Rápido

1. El Trío de la Explotación Cloud

Los tres labs comparten la misma cadena de ataque con adaptaciones específicas de cada proveedor:

Fuga de información
       ↓
 Puerto de entrada (app web con SSRF + RCE)
       ↓
 Metadata Service (http://169.254.169.254/)
       ↓
 Credenciales temporales
       ↓
 Enumeración de recursos cloud
       ↓
 Extracción de datos sensibles
Proveedor IMDS Header Formato de credenciales API de gestión
AWS Ninguno (IMDSv1) AccessKeyId + SecretAccessKey + Token AWS CLI / API
Azure Metadata: true access_token (JWT) Azure REST API
GCP Metadata-Flavor: Google access_token (OAuth2) Cloud Resource Manager API

2. OSINT y Reconocimiento

Teoría

El OSINT (Open Source Intelligence) en cloud consiste en descubrir recursos expuestos sin necesidad de credenciales. Las empresas suelen nombrar sus recursos con patrones predecibles (prod, dev, staging, test, etc.).

Práctica

Lab Herramienta Concepto Lo que pasó
AWS cloud_enum Brute-force de naming permutations El bucket cwl-metatech-prod estaba público. cloud_enum prueba cientos de combinaciones (cwl-metatech-{prod,dev,test,1,2,...}) contra S3.
Azure gobuster dns Enumeración de subdominios internal.meta-tech.cloud resolvió a una IP de Azure. Un subdominio "internal" que debería ser privado estaba expuesto.
GCP GitHub search Supply chain recon / secret leakage El repo público cwl-metatech/production-data contenía una key de service account en base64 dentro de un pipeline CI/CD.

Conexión teoría-práctica

OSINT cloud:
  ├── Buckets S3 → cloud_enum, bucketkicker
  ├── Subdominios → gobuster, subfinder, amass
  ├── Repos GitHub → búsqueda manual, trufflehog, git-secrets
  └── Certificates → crt.sh, censys

3. Fuga de Código Fuente (.git)

Teoría

Por defecto, los servidores web sirven archivos estáticos. Si el directorio .git (repositorio de Git) está accesible, cualquier persona puede descargar todo el historial del proyecto, incluyendo:

  • Código fuente completo
  • Credenciales hardcodeadas (aunque se hayan "eliminado" en commits posteriores)
  • Configuraciones de infraestructura
  • Keys de API

Práctica

Tanto AWS como Azure tenían .git expuesto en la raíz del servidor web. Usamos git-dumper para clonar el repositorio remoto.

git-dumper http://IP/.git /tmp/gitdump

Esto nos permitió leer process.php y descubrir las vulnerabilidades SSRF y RCE.

Diferencia clave entre Git y Cloud: El .git es una mala práctica de desarrollo, no un problema de cloud. Pero es el vector de ataque inicial que permite acceder al cloud.


4. SSRF + RCE — El Caballo de Troya Web

Teoría

SSRF (Server-Side Request Forgery): Vulnerabilidad que permite a un atacante hacer que el servidor web haga peticiones HTTP a destinos arbitrarios. En cloud, el destino más valioso es http://169.254.169.254/ — la IP mágica del Metadata Service.

RCE (Remote Code Execution): Permite ejecutar comandos arbitrarios en el servidor. Útil para ejecutar curl contra el metadata service y obtener credenciales.

Práctica

Los tres labs tenían el mismo process.php:

$ip = $_POST['ip'];
$content = file_get_contents($ip);   // SSRF

$org = $_POST['organization'];
$org_output = system($org);          // RCE

echo $org_output, $content;
Campo Uso normal Uso malicioso
ip Validar IP del site http://169.254.169.254/... (SSRF)
organization Nombre de la organización curl -s http://169.254.169.254/... (RCE)

Conexión teoría-práctica

Servidor web vulnerable
  ├── El parámetro "ip" se pasa a file_get_contents()
  │     → No hay validación → SSRF
  │     → Podemos pedirle al servidor que consulte cualquier URL
  │
  ├── El parámetro "organization" se pasa a system()
  │     → No hay sanitización → RCE
  │     → Podemos ejecutar cualquier comando del sistema
  │
  └── Metadata Service (169.254.169.254)
        → Es una IP link-local, solo accesible desde la máquina
        → Devuelve credenciales temporales de la instancia
        → AWS: sin header | Azure: Metadata:true | GCP: Metadata-Flavor:Google

5. Instance Metadata Service (IMDS)

Teoría

El Metadata Service es un endpoint HTTP interno en 169.254.169.254 que todas las instancias cloud tienen. Proporciona:

  • Información de la instancia (IP, hostname, zona)
  • Credenciales temporales del IAM role / managed identity asociado

Esto es por diseño: las aplicaciones dentro de la instancia necesitan credenciales sin tener que almacenarlas.

Práctica

Concepto AWS Azure GCP
URL base /latest/meta-data/ /metadata/instance?api-version=2021-02-01 /computeMetadata/v1/
Header requerido ❌ Ninguno Metadata: true Metadata-Flavor: Google
Credenciales /latest/meta-data/iam/security-credentials/{role} /metadata/identity/oauth2/token?resource={api}&api-version=2018-02-01 /computeMetadata/v1/instance/service-accounts/default/token
Formato JSON plano JWT OAuth2 token
Lo que obtuvimos AccessKeyId + SecretAccessKey + Token access_token (JWT) access_token

Ejemplo de cómo se ve cada uno:

// AWS
{
  "AccessKeyId": "ASIATQGVY3V5ZIVFIUEQ",
  "SecretAccessKey": "VWGLgRZnNj4spEDc+CuOgJB4U0D3M7/KuPvp+uz0",
  "Token": "IQoJb3JpZ2lu..."
}

// Azure JWT (decodificado)
{
  "iss": "https://sts.windows.net/68b40a4c-.../",
  "tid": "68b40a4c-...",
  "oid": "3c19c764-...",
  "xms_mirid": "/subscriptions/4ebaca3d-.../resourceGroups/.../it-vm"
}

// GCP
{
  "access_token": "ya29.c.c0AZ4bNpa...",
  "expires_in": 3599,
  "token_type": "Bearer"
}

Por qué esto es crítico

SSRF + Metadata Service = credenciales cloud en 3 pasos:

1. Encuentra un SSRF en la app web
2. Apunta a http://169.254.169.254/<ruta según proveedor>
3. Obtén credenciales que te permiten usar la API de cloud

Diferencia clave: IMDSv1 vs IMDSv2

AWS tiene dos versiones:

  • IMDSv1 (la que usamos): No requiere header → vulnerable a SSRF simple
  • IMDSv2: Requiere header X-aws-ec2-metadata-token obtenido mediante PUT request → más seguro

El lab usaba IMDSv1. En un entorno real con IMDSv2, el ataque requiere un paso extra (primero obtener el token PUT).


6. IAM / RBAC / Cloud IAM

Teoría

Cada proveedor tiene su sistema de identidad y permisos:

Concepto AWS Azure GCP
Identidad IAM User / Role User / Service Principal / Managed Identity Service Account
Permiso IAM Policy Role Definition Custom Role
Asignación Policy attached to User/Role Role Assignment IAM Policy Binding
Scope ARN (recurso específico) Scope (subscription, RG, resource) Project, Folder, Organization
Política administrada AWS Managed Policy Built-in Role Predefined Role

Práctica

AWS — IAM Enumeration

Después de obtener las credenciales de EC2:

aws iam list-users                   # emp001, emp002, emp003, int001
aws iam list-groups                  # employees, interns
aws iam get-group --group-name interns       # int001
aws iam list-groups-for-user --user-name emp003  # employees
aws iam list-roles                   # crossaccount-role, dev-role, devops-role, ec2-role
aws iam list-user-policies --user-name emp001  # s3-administrator-Policy
aws iam list-attached-group-policies --group-name employees

Lo que aprendimos de IAM en AWS:

  • Los roles tienen Trust Policies que definen QUIÉN puede asumirlos
  • crossaccount-role permitía al usuario manager de otra cuenta (058264439561) asumirlo
  • dev-role permitía a devops-role asumirlo (chain de roles)
  • Las inline policies están pegadas directamente al usuario (emp001)
  • Las managed policies se附an a grupos (employees → AmazonDevOpsGuruFullAccess)

Azure — RBAC + Graph API

Con el token JWT de Azure:

# Management API: consultar role assignments
curl -H "Authorization: Bearer $MGMT_TOKEN" \
  "https://management.azure.com/subscriptions/$SUB/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01&\$filter=principalId+eq+'$OID'"

# Microsoft Graph API: consultar Entra ID
curl -H "Authorization: Bearer $GRAPH_TOKEN" \
  "https://graph.microsoft.com/v1.0/groups?\$filter=displayName+eq+'IT+Ops'"

curl -H "Authorization: Bearer $GRAPH_TOKEN" \
  "https://graph.microsoft.com/v1.0/applications?\$filter=displayName+eq+'dev-app'"

Lo que aprendimos de Azure:

  • Managed Identity asigna un Service Principal a la VM
  • El role assignment dice qué rol tiene esa identidad a cierto scope
  • Los custom roles definen permisos específicos (ej: Microsoft.Resources/subscriptions/resourceGroups/read)
  • Microsoft Graph API permite enumerar Entra ID: grupos, usuarios, aplicaciones y sus permisos
  • Dos tokens distintos: Management API (Azure resources) y Graph API (Entra ID)

GCP — Cloud IAM

Con el token de la VM:

# Leer IAM policy del proyecto
curl -H "Authorization: Bearer $VM_TOKEN" \
  -X POST -H "Content-Type: application/json" \
  "https://cloudresourcemanager.googleapis.com/v1/projects/mcrta-exam:getIamPolicy" -d "{}"

# Leer definición de un custom role
curl -H "Authorization: Bearer $VM_TOKEN" \
  "https://iam.googleapis.com/v1/projects/mcrta-exam/roles/VMReadgek"

Lo que aprendimos de GCP:

  • Las service accounts son el equivalente a IAM roles en AWS
  • Los custom roles definen permisos específicos (compute.instances.list)
  • Los bindings asocian miembros (service accounts) a roles
  • Cloud Resource Manager API expone la política IAM completa
  • Distintas SAs tienen distintos niveles de acceso:
    • dev-service-account: solo VMReadgek (list instances)
    • vm-service-account: roles/reader a nivel proyecto + acceso a storage
    • terraform-automation: accesso administrativo completo

Jerarquía de permisos en cada cloud

AWS:
  Cuenta → IAM User/Role → Policy (JSON con Effect/Action/Resource)

Azure:
  Tenant → Subscription → Resource Group → Resource
  ↓
  Managed Identity + Role Definition + Scope = Permiso efectivo

GCP:
  Organization → Folder → Project → Resource
  ↓
  Service Account + IAM Role + Binding = Permiso efectivo

7. Storage Buckets

Teoría

Los buckets de almacenamiento cloud son contenedores de objetos. Por defecto son privados, pero las malas configuraciones los dejan públicos.

Proveedor Servicio Acceso público Autenticación alternativa
AWS S3 --no-sign-request AWS SigV4
Azure Blob Storage Allow anonymous access SAS tokens, RBAC
GCP GCS (Cloud Storage) allUsers / allAuthenticatedUsers OAuth2 tokens

Práctica

Lab Bucket Contenido Cómo accedimos
AWS cwl-metatech-prod dev-server-ip.txt, prod-data.txt, staging-data.txt Público, sin credenciales
GCP stag-storage-metatech-prod11 license-key.txt Token de VM (autenticación)

AWS: El bucket estaba completamente público — ni siquiera necesitábamos credenciales. GCP: El bucket requería autenticación, pero el token de la VM tenía permisos roles/reader y roles/storage.admin para acceder.


8. APIs de Gestión Cloud

Teoría

Cada cloud tiene una API REST para gestionar recursos. Con credenciales válidas, podemos llamar a estas APIs para enumerar y modificar recursos.

Práctica

AWS usamos AWS CLI (que internamente llama a las APIs):

aws iam list-users        # → GET /?Action=ListUsers
aws s3 ls s3://bucket     # → GET /bucket

Azure usamos curl directamente contra las REST APIs:

# Management API
https://management.azure.com/subscriptions/{id}/...?api-version=2022-04-01

# Graph API
https://graph.microsoft.com/v1.0/groups/...
https://graph.microsoft.com/v1.0/applications/...

GCP mezclamos gcloud CLI y curl:

gcloud compute instances list
gcloud compute instances describe

# Cloud Resource Manager API
https://cloudresourcemanager.googleapis.com/v1/projects/{id}:getIamPolicy

# IAM API
https://iam.googleapis.com/v1/projects/{id}/roles/{role}

# Storage API
https://storage.googleapis.com/storage/v1/b/{bucket}/o

Diferencia clave:

  • AWS CLI maneja automáticamente el firmado de peticiones (SigV4)
  • Azure REST API usa el token JWT directamente como Bearer token
  • GCP el token OAuth2 también se usa como Bearer

9. Glosario Rápido

Conceptos generales

Término Significado
IMDS Instance Metadata Service — endpoint interno que da info de la instancia
SSRF Server-Side Request Forgery — hacer que un servidor web pida URLs arbitrarias
RCE Remote Code Execution — ejecutar comandos en un servidor remoto
OSINT Open Source Intelligence — recopilación de información de fuentes públicas
IAM Identity and Access Management — quién puede hacer qué en cloud
RBAC Role-Based Access Control — control de acceso basado en roles

AWS

Término Significado
S3 Simple Storage Service — almacenamiento de objetos
IAM Role Identidad con permisos que puede asumir un servicio (EC2, Lambda, etc.)
IAM User Identidad permanente para personas o aplicaciones
IAM Policy Documento JSON que define permisos
Trust Policy Política que define quién puede asumir un rol
Inline Policy Política embebida directamente en un usuario/rol
Managed Policy Política reutilizable creada por AWS o el usuario
ARN Amazon Resource Name — identificador único de un recurso AWS
STS Security Token Service — servicio que emite credenciales temporales

Azure

Término Significado
Managed Identity Identidad automática asignada a un recurso Azure (similar a IAM Role)
Service Principal Identidad de una aplicación en Entra ID
JWT JSON Web Token — formato del token de acceso
Tenant ID (tid) Identificador del inquilino de Entra ID
Subscription ID Identificador de la suscripción de Azure
Scope Alcance donde se aplica un role assignment
Role Definition Conjunto de permisos (similar a IAM Policy)
Role Assignment Asignación de un rol a un principal en un scope
Entra ID Directorio de identidades de Microsoft (antes Azure AD)
Microsoft Graph API unificada para acceder a Entra ID, O365, etc.

GCP

Término Significado
Service Account Identidad para aplicaciones y VMs (similar a IAM Role)
Project ID Identificador único del proyecto GCP
Custom Role Rol personalizado con permisos específicos
Binding Asociación de un miembro a un rol en la política IAM
GCS Google Cloud Storage — almacenamiento de objetos
Cloud Resource Manager API para gestionar proyectos y políticas IAM
OAuth2 token Formato del token de acceso de GCP

Mapa Mental del Ataque

                        ┌─────────────────────────┐
                        │   OSINT / Reconocimiento │
                        │  ┌──────┬──────┬──────┐  │
                        │  │ AWS  │Azure │ GCP  │  │
                        │  │S3    │DNS   │GitHub│  │
                        │  └──────┴──────┴──────┘  │
                        └───────────┬─────────────┘
                                    │
                                    ▼
                        ┌─────────────────────────┐
                        │   App Web Vulnerable     │
                        │  (.git expuesto)         │
                        │  ┌───────────────────┐   │
                        │  │  process.php       │   │
                        │  │  SSRF: ip param    │   │
                        │  │  RCE: org param    │   │
                        │  └───────────────────┘   │
                        └───────────┬─────────────┘
                                    │
                    ┌───────────────┼───────────────┐
                    ▼               ▼               ▼
              ┌──────────┐   ┌──────────┐   ┌──────────┐
              │AWS IMDS  │   │Azure IMDS│   │GCP IMDS  │
              │No header │   │Metadata  │   │Metadata- │
              │          │   │: true    │   │Flavor:   │
              │          │   │          │   │Google    │
              └────┬─────┘   └────┬─────┘   └────┬─────┘
                   │              │              │
                   ▼              ▼              ▼
              ┌──────────┐   ┌──────────┐   ┌──────────┐
              │Credenciales AWS  │JWT Token │   │OAuth2    │
              │(AK+SAK+Token)│   │  Azure   │   │Token GCP │
              └────┬─────┘   └────┬─────┘   └────┬─────┘
                   │              │              │
                   ▼              ▼              ▼
              ┌──────────┐   ┌──────────┐   ┌──────────┐
              │IAM Enum  │   │Azure REST│   │GCP CRM   │
              │AWS CLI   │   │+ Graph   │   │+ Storage │
              │          │   │  API     │   │  API     │
              └──────────┘   └──────────┘   └──────────┘

Conclusión

Los tres labs demuestran el mismo principio fundamental: el Metadata Service (169.254.169.254) es el "santo grial" del hacking cloud porque convierte una vulnerabilidad web (SSRF) en acceso completo a la nube.

Las diferencias entre proveedores son superficiales:

  • Cambian los headers requeridos
  • Cambian los formatos de las credenciales
  • Cambian los nombres de los conceptos (IAM Role vs Managed Identity vs Service Account)
  • Cambian las APIs para enumerar

Pero el flujo de ataque es idéntico:

Encontrar recurso expuesto → Explotar SSRF → Robar credenciales IMDS → Enumerar cloud

Y la defensa también es la misma para los tres:

  1. No exponer .git ni información sensible
  2. Validar inputs contra SSRF
  3. Usar IMDSv2 (AWS) / headers restrictivos
  4. Principio de mínimo privilegio en IAM
  5. Buckets privados por defecto