Comprenda el riesgo de sus políticas. Haga preguntas sobre políticas en lenguaje natural. Solicitar un demo →

Published:

Rompiendo las cadenas de ataque en AWS: roles de IAM

by FireMon

Durante el último año he visto un enorme aumento del interés por obtener consejos concretos sobre cómo manejar incidentes de seguridad dentro del cloud, con técnicas cloud nativas. A medida que las organizaciones trasladan sus cargas de trabajo de producción al cloud, no pasa mucho tiempo antes de que los profesionales de seguridad se den cuenta de que los fundamentos, aunque conceptualmente similares, son bastante distintos en la práctica. Uno de esos conceptos centrales es el de la kill chain, término acuñado por primera vez por Lockheed Martin para describir el proceso del atacante. Si rompe cualquier eslabón, rompe el ataque, por lo que esto encaja bien con la combinación de la defensa en profundidad con los componentes activos de la respuesta a incidentes.

En las implementaciones en el cloud tenemos cuatro grandes categorías de ataque, cada una con kill chains distintas:

  1. Ataques a la propia plataforma cloud. Si dejamos de lado un compromiso fundamental del proveedor de cloud (fuera del alcance del cliente del cloud), estos ataques se centran normalmente en configuraciones incorrectas de los servicios cloud. Si deja un bucket de S3 público, no coloca un autorizador en un API Gateway o expone sus credenciales de AWS en GitHub, entra en esta categoría.
  2. Ataques a recursos y aplicaciones desplegados por el cliente en el cloud. Estos ataques tradicionales no se diferencian de los que se ejecutan contra su centro de datos. Ejemplos comunes incluyen la inyección SQL en una aplicación web y servidores vulnerables con los puertos equivocados abiertos a Internet. Suelen estar algo más acotados de lo que estarían contra un centro de datos, suponiendo que utilice cuentas/suscripciones/proyectos y VPCs o redes virtuales para limitar el radio de impacto.
  3. Ataques contra sus administradores y desarrolladores de cloud. La próxima vez que realice una prueba de penetración, asegúrese de permitir que los atacantes intenten hacer phishing a sus desarrolladores y administradores. Esta es una de las mejores formas de pivotar hacia el cloud, ya que a menudo es mucho más fácil para un atacante obtener acceso al sistema de un desarrollador que vulnerar la propia aplicación cloud. Trataremos esto en el futuro, pero por ahora empecemos diciendo “la MFA es mi amiga”.
  4. Ataques combinados. Esta es la categoría en la que nos centraremos hoy. En estos ataques, el actor de amenazas irrumpe en algo desplegado en el cloud y luego lo utiliza para pivotar hacia el plano de gestión del cloud. (Algunos considerarían que los ataques contra los desarrolladores son combinados, pero prefiero tratarlos por separado).

Como regla general, siempre parto del supuesto de que cualquier ataque exitoso en cualquier nivel puede escalar o pivotar hacia un ataque combinado, momento en el que la seguridad de su plano de gestión y la respuesta a incidentes se convierten en sus mejores defensas.

Hoy me centraré en uno de los procesos de ataque combinado más comunes y describiré una mezcla de controles de detección y de prevención para ayudar a romper la kill chain. Antes de entrar en los detalles, no tome este artículo como una simplificación excesiva de un problema complejo. Gestionar a escala lo que voy a exponer es increíblemente difícil incluso cuando se sabe lo que se hace.

En las próximas semanas comenzaremos a desplegar nuestros primeros Ops diseñados específicamente para estos problemas entre nuestros clientes de acceso anticipado, y deberíamos tenerlos en producción relativamente poco después.

El ataque combinado en AWS: extracción de credenciales de roles de IAM

En un ataque combinado, el actor de amenazas irrumpe en algo más tradicional y luego lo utiliza para pivotar hacia el plano de gestión del cloud. Hay tres formas principales en que esto ocurre. En cada caso, el atacante extrae credenciales estáticas almacenadas o credenciales efímeras de roles de IAM, lo que explicaremos en un minuto.

  1. Compromiso directo de una instancia o un contenedor. Por ejemplo, si deja el puerto 22 abierto y el atacante puede entrar u obtener acceso al shell de otra manera.
  2. Falsificación de solicitudes del lado del servidor (SSRF). El atacante aprovecha (normalmente) una vulnerabilidad de un servidor o servicio web y puede ejecutar comandos sin obtener acceso al shell.
  3. Compromiso de una función Lambda. Aunque no se puede obtener un shell en una Lambda, siguen estando sujetas a vulnerabilidades de ejecución de código e incluso a la ejecución de código arbitrario si contienen un fallo de aplicación. Las implicaciones exactas pueden parecerse a las de SSRF.

En cada caso, el objetivo del atacante es obtener credenciales del plano de gestión de AWS y luego aprovechar los privilegios existentes o escalar privilegios. Trataremos la escalada de privilegios en un artículo futuro; por ahora nos centraremos en qué son esas credenciales y cómo puede evitar su uso indebido.

La mayoría de las personas entiende las credenciales estáticas; en AWS son una Access Key y una Secret Key. Son como un nombre de usuario y una contraseña, pero se utilizan para las llamadas a la API de AWS. La versión actual utiliza un proceso criptográfico conocido como Signature 4 para firmar las solicitudes HTTP cuando realiza esas llamadas a la API. Puede y debe tratarlas igual que un nombre de usuario y una contraseña, y nunca debe almacenarlas dentro de recursos cloud como instancias y Lambdas.

Los roles de IAM son más complicados cuando uno empieza en AWS: son a la vez estupendos y temibles. Un IAM Role en AWS es, en la práctica, un contenedor de permisos que se utiliza para una sesión. Los IAM Roles son excelentes porque no son credenciales como tal… cuando usted asume el rol, AWS proporciona un conjunto de credenciales para una sesión limitada en el tiempo. Los roles son algo exclusivo “del interior de AWS”. Puede asignarlos a recursos dentro de AWS (como una instancia o una función Lambda) y ese recurso puede ahora realizar llamadas a la API ¡sin credenciales estáticas almacenadas! Utilizamos roles para las conexiones de identidad federada, las instancias, las funciones Lambda y todos los demás servicios dentro de AWS. Las access keys se usan realmente solo cuando crea un usuario en una cuenta de AWS; para todo lo demás usamos roles.

Los roles tienen cuatro tipos de permisos asociados:

  1. Lo que el rol puede hacer dentro de AWS. Son simplemente las políticas de permisos que adjunta al rol.
  2. Quién o qué puede usar el rol (la política de confianza). Crear un rol no significa que cualquier cosa o cualquier persona pueda usarlo; esta política restringe el acceso, por ejemplo, a instancias de AWS o a una función Lambda específica.
  3. Un límite de permisos para limitar el alcance del rol. Esto es algo más complejo y no es relevante para nuestra discusión de hoy, así que lo trataremos más adelante.
  4. Cuando asume un rol para una sesión, también puede especificar un subconjunto de sus permisos existentes para utilizarlo en esa sesión. Es una función interesante para el mínimo privilegio, pero tampoco es del todo relevante para nuestra discusión de hoy.

Probablemente sea más fácil explicar cómo funciona esto recorriéndolo paso a paso. Supongamos que tengo una aplicación que necesita acceder a un bucket de S3 o a una base de datos Dynamo. Creo un rol de IAM para la instancia y configuro la política de confianza para que el servicio EC2 pueda usar el rol. Luego lanzo una instancia y le asigno el rol. AWS ejecuta la instancia y hace que la instancia asuma el rol. Asumir el rol abre una sesión y asigna una access key, una secret key y un token de sesión. AWS luego rota esas credenciales cada 1-6 horas y la instancia puede ahora realizar esas llamadas a la API autorizadas por las políticas de permisos.

Aunque las credenciales no están en la instancia, las credenciales siguen siendo accesibles para la instancia. Cualquier código que se ejecute dentro necesita conocer las credenciales para realizar las llamadas reales a la API y acceder a S3 y Dynamo, de modo que algo conocido como el servicio de metadatos las proporciona bajo demanda. El servicio de metadatos es algo especial en AWS para instancias y contenedores que contiene toda la información sobre cómo están configurados. Es bastante importante que un servidor pueda obtener su dirección IP, por ejemplo.

Aquí es donde entra el ataque.

El servicio de metadatos es simplemente una url a la que se puede acceder y que devuelve la información solicitada. curl 169.254.169.254/latest/meta-data/ proporcionará toda la información básica, y puede usar la ruta curl 169.254.169.254/latest/meta-data/iam-security-credentials/ que proporcionará la access key, la secret key y el token. (En el caso de un ataque basado en Lambda, todo esto se ve diferente y se utiliza código del SDK en lugar de curl, pero se aplican los mismos principios).

El atacante puede entonces copiar esas credenciales y usarlas en otro lugar, incrustándolas en herramientas en vez de tener que cargar y ejecutar código en el servidor comprometido. Además, al estar basado en URL, expone el servicio de metadatos a una gama más amplia de ataques SSRF, ya que no se necesita la ejecución completa de código arbitrario. Las credenciales expirarán en algún momento, pero según el ataque podrían simplemente volver y obtener un nuevo conjunto cuando vean que las actuales dejan de funcionar.

Hoy en día, los atacantes inteligentes utilizarán las credenciales en una cuenta de AWS que ellos controlan, ya que Amazon dispone de herramientas para detectar credenciales extraídas y utilizadas fuera de sus rangos de direcciones conocidos.

Rompiendo la cadena de ataque de extracción de roles de IAM

Tracemos la cadena de ataque. El atacante necesita hacer lo siguiente:

  • Descubrir y explotar una vulnerabilidad en una instancia, un contenedor o una función Lambda que le permita acceder a las credenciales del rol. Esto casi siempre es un error del lado del cliente… como no aplicar parches, abrir los puertos equivocados o desplegar código vulnerable.
  • Extraer las credenciales actuales del rol.
  • Ejecutar con éxito llamadas a la API permitidas en un entorno bajo su control.
  • Hacer algo malicioso dentro del alcance de la política de permisos del rol de IAM permitido. Bueno, probablemente malicioso, no es que la mayoría de los atacantes le apliquen parches a su código.

Las siguientes técnicas pueden romper distintos eslabones de la cadena e incluyen una combinación de controles de detección y de prevención. No se sienta mal si esto parece abrumador… muy, MUY pocas de las organizaciones con las que trabajo implementan esto de forma integral, especialmente a escala.

6 técnicas para ayudar a romper distintos eslabones de la cadena de ataque

  1. Gestión de vulnerabilidades
  2. Políticas de permisos de IAM con privilegios mínimos y restricciones de recursos
  3. Usar restricciones condicionales de IP, VPC u otro origen de solicitud en las políticas de permisos
  4. Usar endpoints de servicio con políticas + políticas de recursos
  5. Agregar proxies de metadatos con filtros de User Agent HTTP (protección del servicio de metadatos)
  6. Protección contra el uso duplicado de roles

Gestión de vulnerabilidades

  • Complejidad: moderada
  • Eficacia: baja
  • Escalabilidad: difícil
  • Tipo: de detección y de prevención

No sorprende que su punto de partida deba ser eliminar todas las vulnerabilidades y configuraciones erróneas iniciales que el atacante puede usar para pivotar y obtener credenciales. Solo califiqué la complejidad como moderada porque no hay nada nuevo ni específico del cloud en esto. Pero también califico la eficacia como baja, ya que no es que la gestión integral de vulnerabilidades haya evitado las legiones de brechas de seguridad de las últimas décadas. Simple en concepto, increíblemente complejo a escala.

Políticas de permisos de IAM con privilegios mínimos y restricciones de recursos

  • Complejidad: moderada
  • Eficacia: alta
  • Escalabilidad: de moderada a difícil
  • Tipo: de prevención

Las políticas de IAM en AWS son de denegación predeterminada e incluyen declaraciones explícitas de permiso y de denegación. Por ejemplo, puede escribir una política que solo permita leer un bucket de S3. También incluyen restricciones de recursos, de modo que, mientras la declaración de permiso autoriza al rol a llamar a la API de lectura, la restricción de recursos solo le permite al rol leer buckets u objetos específicos. Siempre, SIEMPRE debe comenzar sus defensas aquí. Cuando realizo evaluaciones, encuentro, en casi todos los proyectos, políticas de IAM que permiten demasiados privilegios (las llamadas a la API) y muy pocas restricciones de recursos. Sí, ese servicio puede necesitar acceso a una base de datos Dynamo, pero ¿necesita acceso a todas las tablas? Este control en particular no es tan difícil de implementar a pequeña escala, pero cuanto más grande es la organización y cuantas más personas toman estas decisiones de políticas, más difícil es ser consistente a escala. También es importante agregar declaraciones explícitas de denegación por si alguien agrega una nueva política con nuevos permisos al rol. Los permisos son acumulativos, pero cualquier declaración de denegación anula las declaraciones de permiso.

Usar restricciones condicionales de IP, VPC u otro origen de solicitud en las políticas de permisos

  • Complejidad: alta
  • Eficacia: de moderada a alta
  • Escalabilidad: difícil
  • Tipo: de prevención

Las políticas de IAM admiten declaraciones condicionales que soportan diversas opciones, incluida la dirección IP o la VPC de origen. Si sabe que un rol en particular solo debería realizar llamadas a la API desde un recurso específico de su stack de aplicaciones, puede restringir la autorización a esa dirección IP o subred exacta. Si el atacante roba las credenciales e intenta usarlas en otro lugar, las llamadas a la API fallarán. Este es un mazo de precisión guiada: fácil en concepto y difícil en la ejecución, ya que puede encontrar otras complejidades que interfieran con una implementación adecuada. Por ejemplo, las llamadas a la API hacia los servicios de AWS salen directamente a Internet, pasan por una NAT Gateway o se enrutan internamente con un endpoint de servicio (que analizaremos en un momento). La dirección IP detectada dependerá de la ruta que siga la llamada a la API hacia Internet. Todo esto es manejable y detectable (y automatizable), pero conviene que se informe primero para asegurarse de comprender las permutaciones.

Consulte la primera parte de esta publicación de Netflix para ver algunos ejemplos.

A menos que ejecute su función Lambda en una VPC, esta no será una opción para proteger una función comprometida.

Usar endpoints de servicio con políticas + políticas de recursos

  • Complejidad: moderada
  • Eficacia: de moderada a alta
  • Escalabilidad: moderada
  • Tipo: de prevención

En AWS, un endpoint de servicio es como una derivación en la red que toma el tráfico que normalmente iría por Internet hacia un servicio de AWS y lo reenruta internamente. Originalmente se crearon para permitir que las subredes totalmente privadas en AWS, aquellas sin ninguna forma de alcanzar Internet, pudieran acceder de todos modos a ciertos servicios de AWS. Los endpoints admiten políticas que puede usar para restringir el acceso y las acciones de maneras muy similares a las políticas de IAM. En este caso, agrega restricciones a la política del endpoint para permitir solo el acceso a recursos específicos detrás de ese endpoint (S3 es el ejemplo más común). Usted especifica qué buckets están permitidos, y ningún otro recurso de esa subred tiene acceso a ese servicio. Piense en esto como un respaldo a la política de IAM: con un endpoint de servicio que usa una política restrictiva, incluso si alguien accidentalmente (o deliberadamente) le otorga al rol un acceso más amplio del que debería tener, aun así no podrá acceder a nada que no esté permitido en la política del endpoint de servicio. Esto significa que ahora tenemos tres capas de políticas, todas las cuales deben permitir el acceso al recurso:

  • La política de permisos de IAM que le permite al rol acceder al recurso.
  • La política del endpoint de servicio que permite el acceso a los recursos cuando las solicitudes llegan a través del endpoint, sin importar los permisos del rol utilizado.
  • La política del bucket o del recurso (esto depende del tipo de recurso), que puede restringir el acceso únicamente a las direcciones IP aprobadas.

A menos que ejecute su función Lambda en una VPC, esta, nuevamente, no será una opción para proteger una función comprometida.

Agregar proxies de metadatos con filtros de User Agent HTTP (protección del servicio de metadatos)

  • Complejidad: alta
  • Eficacia: moderada
  • Escalabilidad: difícil
  • Tipo: de prevención

Todos estos controles asumen que un atacante puede robar las credenciales del rol, pero ¿y si tuviéramos una forma de reducir su capacidad de obtener esas credenciales incluso si compromete la instancia o el contenedor autorizado? (Esta técnica no funcionará para funciones Lambda). Una opción emergente es restringir el acceso al servicio de metadatos desde el principio. Aunque ha habido algunos intentos de hacerlo con IPTables, eso también podría romper funcionalidad necesaria para el código que tiene en ejecución en la instancia. En noviembre de 2018, AWS y Netflix trabajaron juntos y comenzaron a agregar datos de usuario a los encabezados HTTP de las llamadas a la API realizadas desde los SDK de AWS. Esta es una defensa contra SSRF, ya que la mayoría de los ataques SSRF se basan en engañar a una aplicación para que realice solicitudes HTTP en nombre del atacante, pero esas solicitudes suelen provenir de una herramienta de línea de comandos como curl u otro proceso y carecerán del encabezado de datos de usuario que proviene de los SDK de AWS. Para que esto funcione, necesita insertar un proxy para esas solicitudes. Existen algunas opciones de código abierto para instancias y contenedores, incluidos proxies que se ejecutan en la propia instancia en lugar de requerir que enrute el tráfico a un appliance virtual o a un proxy squid.

Esta técnica no funcionará si el atacante compromete la instancia host y ejecuta un shell, ya que puede deshabilitar el Roxy o secuestrar el proceso aprobado.

Puede leer todo al respecto en los detalles de esta publicación de Netflix.

Protección contra el uso duplicado de roles

  • Complejidad: alta
  • Eficacia: alta
  • Escalabilidad: alta
  • Tipo: de detección

Esta es otra que proviene del equipo de Netflix. Publicaron una guía de una excelente técnica para detectar cuándo se está usando un rol de IAM en una ubicación no autorizada, incluso dentro de AWS. Recomiendo encarecidamente que lea la publicación enlazada, pero la versión corta es que combinan los registros de CloudTrail con otras herramientas para mantener una tabla de qué instancias usan qué roles desde qué direcciones IP. Luego monitorean otras llamadas a la API para detectar cuándo un rol se está reutilizando desde una nueva dirección IP al mismo tiempo que está en uso desde una aprobada. Con este método no necesita conocer todas las direcciones IP en uso en toda la organización: construye dinámicamente una tabla de lo que está en uso y detecta cuándo ese rol se está usando en otro lugar al mismo tiempo. Esto es extremadamente escalable, ya que puede ejecutar la lógica de forma centralizada si centraliza CloudTrail, lo cual de todas formas es una práctica recomendada habitual.

Resumen

Esta es otra publicación enorme, y no esperamos que todos puedan implementar cada una de estas opciones en todos los despliegues. Para simplificar, repasemos la cadena de ataque de abuso de roles de IAM:

  • Descubrir y explotar una vulnerabilidad en una instancia, un contenedor o una función Lambda que le permita acceder a las credenciales del rol. Esto casi siempre es un error del lado del cliente… como no aplicar parches, abrir los puertos equivocados o desplegar código vulnerable.
    • La gestión de vulnerabilidades (incluidas herramientas como SASST y DAST para aplicaciones) y la evaluación de su configuración de cloud (con herramientas como DisruptOps o herramientas de código abierto como Prowler y CloudMapper) son su primera defensa.
  • Extraer las credenciales actuales del rol.
    • Protección del servicio de metadatos y gestión de vulnerabilidades
  • Ejecutar con éxito llamadas a la API permitidas en un entorno bajo su control.
    • Detección del uso duplicado de roles, usar restricciones condicionales de IP, VPC u otro origen de solicitud en las políticas de permisos, usar endpoints de servicio con políticas + políticas de recursos
  • Hacer algo malicioso dentro del alcance de la política de permisos del rol de IAM permitido. Bueno, probablemente malicioso, no es que la mayoría de los atacantes le apliquen parches a su código.
    • Políticas de permisos de IAM con privilegios mínimos y restricciones de recursos

Esperamos que esto le dé un panorama más claro de cómo reducir el éxito de este tipo de ataques.

Cómo detener las cadenas de ataque en AWS IAM | FireMon