Tres ataques de escalada de privilegios en AWS, con la evidencia de CloudTrail y la solución
Puntos clave
- Un ataque de escalada de privilegios en AWS es una secuencia de llamadas a la API que lleva a un principal desde los permisos que tiene hasta permisos que nunca se le concedieron. Las llamadas son ordinarias, y por eso cuesta detectarlas.
- Tres cadenas aparecen una y otra vez en cuentas reales:
iam:PassRoleconlambda:CreateFunction,iam:UpdateAssumeRolePolicyseguido dests:AssumeRole, yiam:CreateAccessKeysobre otro usuario. - Cada cadena deja eventos específicos en CloudTrail. Detectarla consiste en vigilar esos eventos cuando proceden de principales que no tienen motivo para generarlos, con los parámetros de la solicitud como señal.
- Cada cadena tiene una solución concreta: una condición
iam:PassedToService, un permiso eliminado o un Deny sobre la acción específica. En la mayoría de los casos es un solo cambio de política. - Hacen falta tanto la detección como la prevención. CloudTrail te lo dice después de la llamada. Validar las rutas por adelantado te dice qué principales podrían hacer esa llamada siquiera.
Un ataque de escalada de privilegios en AWS es una secuencia de llamadas a la API que lleva a un principal desde los permisos que tiene hasta permisos que nunca se le concedieron. No hay exploit en el sentido habitual. Las llamadas son las mismas que los administradores hacen a diario, y eso es lo que las hace difíciles de notar y fáciles de dejar abiertas. El Mapa de Escalada de Privilegios de AWS recoge cada permiso que puede usarse de esta manera. Este artículo toma tres de las cadenas más comunes y muestra, para cada una, cómo funciona, qué registra CloudTrail y el cambio que la rompe.
Cadena uno: pasar un rol a Lambda
iam:PassRole y lambda:CreateFunction en manos del mismo principal, este crea una función, le entrega un rol privilegiado y la función se ejecuta como ese rol. Ninguno de los dos permisos alarma por sí solo.Permisos. iam:PassRole sobre un rol privilegiado, junto con lambda:CreateFunction. Normalmente también lambda:InvokeFunction, aunque una función también puede activarse mediante un origen de eventos.
Cómo funciona. El atacante crea una nueva función Lambda y le pasa el rol privilegiado como rol de ejecución. AWS acepta el paso porque la política de confianza del rol permite lambda.amazonaws.com. El atacante invoca entonces la función, y el código que haya escrito se ejecuta con los permisos del rol privilegiado. Si ese rol es un administrador, la cuenta es suya tras un create y un invoke. El mismo patrón funciona con EC2, ECS, Glue, CloudFormation, CodeBuild y cualquier otro servicio que acepte un rol pasado.
Qué muestra CloudTrail. Un evento de administración CreateFunction de lambda.amazonaws.com cuyo requestParameters.role es el ARN de un rol privilegiado. La comprobación de iam:PassRole no genera un evento propio; el paso se ve en los parámetros de la llamada de creación. El Invoke posterior es un evento de datos de Lambda, así que solo aparece si el trail tiene habilitados los eventos de datos de Lambda, algo que está desactivado por defecto y que conviene activar precisamente por esta razón. Con ambos en su sitio, la señal es el emparejamiento: un principal que nunca había creado una función crea una con un rol de alto valor asociado y la invoca a los pocos minutos. Sin eventos de datos, la señal es la propia llamada de creación y la actividad de API que el rol pasado realiza después.
La solución. Acota el paso. Añade una condición iam:PassedToService a la concesión de iam:PassRole para que el rol solo pueda pasarse al servicio que lo necesita, y sustituye cualquier comodín en el ARN del recurso por el rol concreto. Si el principal no necesita pasar roles en absoluto, elimina el permiso. Análisis completo: Pasar un rol a Lambda.
Cadena dos: reescribir la política de confianza de un rol y luego asumirlo
Permisos. iam:UpdateAssumeRolePolicy sobre un rol privilegiado, más sts:AssumeRole.
Cómo funciona. La política de confianza de un rol decide quién puede asumirlo. Un principal que pueda reescribir ese documento se añade a sí mismo como principal de confianza, luego llama a sts:AssumeRole y recibe credenciales temporales del rol. La relación de confianza original deja de importar una vez sobrescrita, así que este movimiento toma el control de cualquier rol de la cuenta al que el principal pueda llegar con la llamada de actualización. La política de confianza reescrita permanece hasta que alguien se da cuenta, lo que convierte esto en un mecanismo de escalada y también de persistencia.
Qué muestra CloudTrail. Un evento UpdateAssumeRolePolicy de iam.amazonaws.com con el nuevo documento de política en requestParameters.policyDocument, seguido de un evento AssumeRole de sts.amazonaws.com para el mismo rol, desde el principal que acaba de añadirse. Las políticas de confianza cambian poco en una cuenta sana, así que cualquier evento UpdateAssumeRolePolicy fuera de un pipeline de despliegue merece una revisión, y uno que añade un principal desde dentro de la cuenta es una señal fuerte.
La solución. Elimina iam:UpdateAssumeRolePolicy de cualquier principal que no forme parte de la vía de administración de IAM, y pon un Deny explícito sobre esa acción para los roles privilegiados de la cuenta, con el rol de despliegue como única excepción. Análisis completo: Reescribir la confianza del rol y asumirlo.
Cadena tres: crear una clave de acceso para otro usuario
Permisos. iam:CreateAccessKey sobre un usuario distinto del que hace la llamada.
Cómo funciona. El atacante llama a iam:CreateAccessKey con el nombre de otro usuario y recibe una clave de acceso de larga duración completamente nueva para ese usuario. Nunca necesita la contraseña ni las claves existentes del usuario. A partir de ahí puede llamar a la API como ese usuario, y la nueva clave sobrevive a un restablecimiento de contraseña y a la rotación de la otra clave del usuario. Esta es la más difícil de notar de las tres, porque una sola llamada produce credenciales duraderas y el usuario cuya identidad fue tomada no ve nada.
Qué muestra CloudTrail. Un evento CreateAccessKey de iam.amazonaws.com donde requestParameters.userName difiere de la identidad en userIdentity. Esa discrepancia es la señal. Que los usuarios creen claves para sí mismos es normal. Que un principal cree claves para otro es raro fuera de un script de alta de usuarios, y el rol de ese script es fácil de incluir en una lista de permitidos. El uso posterior aparece como llamadas a la API del usuario víctima desde una IP de origen y un agente de usuario nuevos.
La solución. Elimina iam:CreateAccessKey de todo principal que no forme parte de la vía de administración de identidades, y donde los usuarios deban gestionar sus propias claves, acota la concesión a ${aws:username} para que un usuario solo pueda crear claves para sí mismo. Análisis completo: Crear una clave de acceso para un usuario.
Cómo detectar la escalada de privilegios en AWS
Las tres cadenas anteriores comparten un patrón que se generaliza. La escalada de privilegios deja eventos ordinarios con parámetros inusuales, procedentes de principales sin historial de generarlos. La detección en CloudTrail se apoya en cuatro cosas.
Primero, CloudTrail debe estar activo en cada cuenta y cada región, con el trail entregado a una cuenta central en la que las cargas de trabajo no puedan escribir. Un atacante que pueda desactivar o eliminar el trail elimina la evidencia, y StopLogging y DeleteTrail pertenecen a la misma lista de vigilancia que los eventos de escalada.
Segundo, vigila los parámetros y no solo los nombres de los eventos. CreateFunction por sí solo es rutinario, mientras que CreateFunction con un rol de administrador en los parámetros merece una alerta. Lo mismo ocurre con CreateAccessKey cuando el usuario objetivo difiere del que hace la llamada.
Tercero, establece una línea base por principal. Un rol de CI que crea una función cada hora y un desarrollador que no ha llamado a IAM en un año son fuentes distintas, y el mismo evento desde cada uno significa cosas distintas.
Cuarto, empareja los eventos. La escalada es una secuencia: crear y luego invocar, actualizar la confianza y luego asumir, crear la clave y luego usarla desde un lugar nuevo. Una regla que une el primer evento con el segundo dentro de una ventana corta produce muchos menos falsos positivos que cualquiera de los dos eventos por separado. La actividad de Lambda, S3 y DynamoDB son eventos de datos y deben habilitarse en el trail antes de poder emparejarse.
La detección es la segunda línea
CloudTrail te lo dice después de que se hizo la llamada. La primera línea es saber, antes de cualquier llamada, qué principales podrían hacerla. Eso significa tomar cada cadena del mapa y resolverla contra la autorización real de la cuenta: políticas de identidad, límites de permisos, SCP, políticas de confianza y condiciones. Una cadena que se resuelve en allow para un principal es una ruta demostrada, y la solución es el cambio descrito arriba, aplicado antes de que alguien lo intente. Pathbreak hace esa resolución en modo de solo lectura en todas las cuentas, clasifica las rutas demostradas según lo que alcanzan y confirma cada solución después de aplicarla. La herramienta gratuita pathbreak-audit enumera qué principales de una sola cuenta tienen estos permisos, como punto de partida.
Preguntas frecuentes
¿Qué es un ataque de escalada de privilegios en AWS?
Un ataque de escalada de privilegios en AWS es una secuencia de llamadas a la API mediante la cual un principal obtiene permisos que no se le concedieron, por ejemplo pasando un rol privilegiado a un servicio que puede crear, reescribiendo la política de confianza de un rol y asumiéndolo, o creando una clave de acceso para un usuario con más privilegios. Pathbreak valida qué principales de tus cuentas de AWS podrían hacer estas llamadas.
¿Cómo se detecta la escalada de privilegios en CloudTrail?
Vigila los eventos específicos que produce cada cadena, como CreateFunction con un rol privilegiado en los parámetros, UpdateAssumeRolePolicy seguido de AssumeRole, o CreateAccessKey donde el usuario objetivo difiere del que hace la llamada. Establece una línea base por principal, empareja el primer evento con el segundo y mantén el trail en una cuenta que las cargas de trabajo no puedan modificar. Pathbreak complementa la detección en CloudTrail mostrando, antes de que se haga ninguna llamada, qué principales podrían hacerla.
¿Es iam:PassRole peligroso por sí solo?
Por sí solo no. Se convierte en una ruta de escalada de privilegios cuando se combina con un permiso que crea o actualiza un recurso de cómputo que acepta un rol, como lambda:CreateFunction o ec2:RunInstances, y cuando el rol objetivo confía en ese servicio. Acotar el paso con iam:PassedToService y un ARN de rol concreto elimina la ruta. Pathbreak comprueba la política de confianza y las condiciones de cada traspaso de rol cuando valida una ruta.
¿Qué solución elimina más rutas de escalada de privilegios?
En la mayoría de las cuentas, acotar o eliminar iam:PassRole sobre los roles privilegiados elimina la mayor parte, porque decenas de servicios aceptan un rol pasado. En la cuenta de laboratorio de Pathbreak, un solo Deny sobre un rol eliminó 3,893 de 4,087 rutas. El primer cambio correcto depende de por qué principales pasan las rutas demostradas.
Descubre qué principales de tus cuentas pueden hacer estas llamadas hoy, antes de que CloudTrail tenga que decírtelo.
Solicitar una demo Ver la demo