BLOG

Superar las limitaciones de Service Mesh para la seguridad de clústeres de aplicaciones distribuidas.

Miniatura de Ankur Singla
Ankur Singla
Publicado el 13 de abril de 2020

Este es el cuarto blog de una serie que cubre diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS :

  1. Plano de control para PaaS de Kubernetes distribuido
  2. Malla de servicios global para aplicações distribuidas
  3. Seguridad de la plataforma para infraestructura distribuida, aplicaciones y datos
  4. Seguridad de aplicação y redes de clústeres distribuidos
  5. Observabilidad en una plataforma distribuida globalmente
  6. Operaciones y SRE de una plataforma distribuida globalmente
  7. Marco de servicios Golang para microservicios distribuidos

En el blog anterior , brindamos información sobre el desafío de usar técnicas criptográficas para proteger nuestra plataforma (infraestructura, aplicaciones y datos). Este blog tratará sobre las técnicas que utilizamos para proteger la plataforma contra ataques dirigidos desde la red, tanto desde Internet como desde dentro. Dado que las aplicaciones ya no están limitadas a ninguna ubicación física, los firewalls tradicionales basados en perímetro y las soluciones de seguridad basadas en firmas ya no son efectivas. Describiremos las deficiencias de nuestra implementación de seguridad de confianza cero inicial y por qué y cómo la aumentamos con aprendizaje automático y técnicas algorítmicas para proteger adecuadamente nuestra infraestructura distribuida y clústeres de aplicaciones.

TL;DR (Resumen)

  1. Nuestros requisitos de seguridad de aplicación a aplicación y de usuario a aplicación se complicaron por el hecho de que nuestra plataforma ejecuta cientos de microservicios (en muchos clústeres de Kubernetes) junto con algunas aplicaciones monolíticas en múltiples proveedores de nube (AWS y Azure), nuestra red global y ubicaciones de borde.
     
  2. También se nos pidió que creáramos procesos y entregáramos una solución robusta de seguridad de red + aplicaciones que brindara acceso selectivo a la infraestructura compartida a nuestros desarrolladores, nuestros equipos de operaciones, los desarrolladores de nuestros clientes, sus equipos de operaciones y sus usuarios finales. Esto se complicó aún más por el hecho de que teníamos que cumplir requisitos de cumplimiento como PCI-DSS, SOC, etc.
     
  3. Si bien ya habíamos creado una solución de confianza cero basada en nuestra red de servicios global y puerta de enlace API, no resolvió muchos problemas de seguridad como la vulnerabilidad del sistema, el agotamiento de recursos, los ataques de Internet por parte de bots/malware y las necesidades de unos pocos servicios que brindaban acceso no autenticado. Además, a veces era difícil para nuestro equipo de secops obtener información de la API de los desarrolladores, algo esencial para una buena implementación de confianza cero que se basa en listas blancas de acceso.
     
  4. Para satisfacer estas necesidades, nuestro equipo de plataforma habría tenido que adquirir servicios de proveedores/proveedores de nube o ampliar nuestra ruta de datos L3-L7+ (detallada aquí ) con funciones de seguridad adicionales: firewall de red, firewall de aplicaciones, protección DDoS, gestión de acceso privilegiado, etc. Dado que ningún proveedor de nube existente podía resolver estos problemas con herramientas que brindaran políticas unificadas, capacidad de observación y capacidades de descubrimiento de API automatizadas, tuvimos que tomar la difícil decisión de embarcarnos en un proyecto interno para aumentar nuestra ruta de datos y nuestro plano de control.
     
  5. Como parte de la construcción de las capacidades de seguridad de la red y la aplicación en DataPath, terminamos agregando muchas características nuevas, algo que aún no se ha logrado en ningún DataPath de red hasta la fecha. Fusionamos capacidades de seguridad algorítmica con aprendizaje automático en el tráfico de red y aplicaciones junto con un motor de políticas programable que funciona en toda la pila: red, HTTP y API. Como resultado, ahora podemos ofrecer diferentes capacidades de seguridad según el entorno de implementación, el modelo de tráfico y las necesidades de latencia. Esto ha hecho que nuestra malla de servicio global sea más segura, ha reducido la cantidad de falsos positivos para nuestro equipo SOC y ha proporcionado una reducción significativa en la latencia y los recursos computacionales.

Limitaciones de la malla de servicios y la arquitectura de confianza cero

Nuestra plataforma ejecuta una gran cantidad de aplicaciones en múltiples equipos que operan sus propios clústeres en el borde, nuestra red global y las nubes públicas de AWS y Azure. Si bien la mayoría de las cargas de trabajo están orquestadas por microservicios mediante Kubernetes, tenemos un puñado de monolitos de gran escala (por ejemplo, elasticsearch) que administramos mediante Terraform. La figura 1 demuestra la naturaleza distribuida de nuestra plataforma. Por ejemplo, en cada uno de nuestros más de 18 PoP de red global (con unas pocas decenas o un poco más de cien servidores físicos), ejecutamos miles de pods de aplicaciones. Sin embargo, en el borde, hoy tenemos implementaciones de clientes individuales con más de 3000 ubicaciones activas (cada una con uno a siete computadores) que ejecutan algunas decenas de pods de aplicaciones.

límites de malla 1
Figura 1: Aplicaciones y datos distribuidos en la plataforma Volterra

La plataforma es totalmente multiinquilino y cada nodo ejecuta cargas de trabajo de diferentes clientes (y las nuestras). Dado que algunas de estas aplicaciones están expuestas a Internet público, debemos asegurarnos de que toda la comunicación hacia/desde las aplicaciones sea segura. Como hemos descrito en los dos blogs anteriores, construimos un sistema robusto de identidad, autenticación y autorización junto con nuestra propia ruta de datos de red L3-L7+ (VoltMesh) que se utiliza para impulsar nuestra malla de servicios y puerta de enlace API . Como se muestra en la Figura 2, esto nos ha permitido brindar seguridad a nivel de transporte en todos los clústeres de aplicaciones (mTLS), desde usuarios (TLS/mTLS) y empleados (mTLS), así como control de acceso basado en autenticación+autorización.

límites de malla 2
Figura 2: Seguridad del transporte con Service Mesh y API Gateway

Si bien esta implementación de confianza cero ofrece muchos beneficios, no resuelve automáticamente varios problemas de seguridad:

  1. Vulnerabilidad del sistema : una aplicación puede verse comprometida debido a una vulnerabilidad del sistema o a un empleado autorizado pero malintencionado; es necesario que exista un mecanismo para detectar dichas situaciones, tomar medidas correctivas automáticamente y alertar a nuestros equipos de SRE.
     
  2. Agotamiento de recursos : hay muchas situaciones en las que incluso el acceso de clientes legítimos y autorizados puede agotar lentamente los recursos de la aplicación debido a un diseño deficiente. Estas situaciones pueden degradar significativamente el rendimiento para otros usuarios.
     
  3. Ataques de Internet : dado que gran parte de nuestra infraestructura y aplicaciones (y las de nuestros clientes) están expuestas directamente a Internet público, estos recursos sufren ataques continuos de usuarios maliciosos, bots y malware. Necesitamos detectar y proteger estos recursos contra ataques de denegación de servicio, volumétricos y de intrusión para brindar un buen tiempo de respuesta a otros usuarios.
     
  4. Servicios no autenticados : si bien la mayoría de las aplicaciones requieren autenticación (también necesaria para la confianza cero), hay casos en los que no se puede restringir una aplicación. Como resultado, estas aplicaciones requieren protección adicional mediante soluciones basadas en red.

Durante los últimos 2,5 años de desarrollo en esta plataforma, también nos dimos cuenta de que, a menudo, nuestros desarrolladores incorporan aplicaciones de código abierto, las contienen en contenedores y le piden a nuestro equipo de DevOps que las implemente en la plataforma. Sin embargo, a menudo carecen de detalles sobre las interacciones a nivel de API dentro de estas aplicaciones que nuestro equipo de seguridad necesita para crear políticas para incluir la comunicación en la lista blanca. Este es un gran obstáculo para nuestra implementación de seguridad de confianza cero, ya que exige políticas de lista blanca que solo permiten las API utilizadas por las aplicaciones y bloquean todo el resto del tráfico. Cada vez que hicimos excepciones a este requisito, algunas aplicaciones quedaron con una segmentación a nivel de red muy básica, lo que aumentó la superficie de ataque.

Ampliando nuestra red de servicios de confianza cero

Como resultado, necesitábamos ampliar nuestra solución de seguridad de confianza cero existente con capacidades de seguridad adicionales para manejar los problemas enumerados anteriormente. Identificamos una lista de capacidades de seguridad adicionales que tuvimos que incorporar a la plataforma:

  1. Descubrimiento y control de API : desarrolle la capacidad de aprender API en aplicaciones en ejecución y automatice la generación de políticas de lista blanca de aplicaciones/API sin depender de los desarrolladores
  2. Detección de anomalías : capacidad de detectar y proteger contra comportamientos anómalos del tráfico de cualquier tipo de origen (usuario o aplicación confiable o no confiable).
  3. Creación de perfiles de comportamiento : proteja las aplicaciones contra el agotamiento de recursos, ataques a aplicaciones/API (de Internet o de la red interna) y contra ataques volumétricos desde Internet a la infraestructura o las aplicaciones.
  4. Registro y visualización : capacidad de registrar y rastrear todos los accesos para futuras necesidades de análisis forense y/o cumplimiento.

Decidimos utilizar una combinación de técnicas tradicionales basadas en firmas, algoritmos estadísticos y enfoques de aprendizaje automático más dinámicos para resolver estos problemas. Esto requirió que hiciéramos cambios en nuestro backend SaaS, así como también agregar nuevas capacidades en nuestra ruta de datos de red.

Aprendizaje profundo para el descubrimiento y control de API

Para proteger la plataforma, solo permitimos conexiones de red según la lista blanca de API para cada aplicación. Esto requiere que nuestro equipo de seguridad se coordine con los desarrolladores y garantice que nuestro motor de políticas programable reciba la información correcta de la API. Rápidamente nos dimos cuenta de que era imposible para nuestros desarrolladores proporcionar esta información para aplicaciones que no se crearon utilizando nuestro marco de servicio.

Dado que nuestro proxy de malla de servicio está en la ruta de red de cada acceso a la aplicación, decidimos aprender las API y los recursos estáticos que expone la aplicación haciendo un análisis en tiempo de ejecución de cada acceso que pasa por el proxy. El desafío de este enfoque es identificar los puntos finales de la API inspeccionando las URL y separando los componentes que se generan dinámicamente. Por ejemplo, para una API “api/user/<user_id>/vehicle/”, el proxy verá accesos como:

Puede haber millones de solicitudes de este tipo, lo que hace que sea muy difícil descifrarlas. Como resultado, la identificación de componentes dinámicos en estas solicitudes relacionadas se realiza mediante aprendizaje profundo y análisis de gráficos. Representamos todo el conjunto de componentes de URL como un gráfico y luego realizamos la agrupación de gráficos para encontrar subgráficos con propiedades similares utilizando conjuntos de características que capturan propiedades específicas de componentes generados dinámicamente, como:

  • Propiedades estructurales
  • Entropía de los nodos
  • Similitud de Jaccard entre varias partes del gráfico
  • Clasificación de cadenas simple utilizando métodos de aprendizaje profundo bien comprendidos

Como resultado, los componentes dinámicos se clasifican y la salida del sistema se ve así:

Al utilizar este aprendizaje automático de API, podemos generar de manera fácil y automática una política que nuestro proxy de malla de servicio pueda aplicar. Con base en los puntos finales de API descubiertos, también aprendemos otras propiedades, como qué aplicaciones usan qué API para comunicarse con otras aplicaciones, el comportamiento típico de estas API, etc. Esto nos permite crear un gráfico de servicios que ayuda a nuestro equipo de seguridad a visualizar la interacción de servicio a servicio para análisis forense, descubrimiento y microsegmentación a nivel de API.

Identificación de deficiencias en los firewalls

Antes de embarcarnos en agregar las dos capacidades restantes (detección de anomalías y creación de perfiles de comportamiento), decidimos ver si las soluciones existentes podrían ayudarnos. Si bien existen muchos firewalls perimetrales y productos de firewall para aplicaciones web en el mercado, la mayoría de estas soluciones están orientadas a proteger las aplicaciones que miran a Internet. Parten de ciertas suposiciones de que el tráfico atendido es tráfico web y brindan protección específica para HTML, javascript, sql, CMS, etc., lo que hace relativamente más fácil escribir firmas y reglas para detectar vulnerabilidades y exploits conocidos.

Si bien esta capacidad es importante para nuestro tráfico web, también necesitamos atender una cantidad cada vez mayor de tráfico de API y de máquina a máquina en nuestro entorno. Para resolver esto, nuestro equipo de seguridad tendría que escribir reglas específicas para la aplicación que no se encuentren dentro de las reglas web típicas conocidas (como OWASP CRS). Generalmente, los administradores de seguridad saben poco sobre las aplicaciones y, dada la naturaleza dinámica del entorno, se vuelve aún más difícil realizar un seguimiento de los tipos y la estructura de las aplicaciones para escribir reglas específicas de cada aplicación. Como resultado, si bien nuestro equipo de plataforma proporciona esta capacidad en nuestra ruta de datos de red, nuestro equipo de seguridad no la utiliza con frecuencia.

Otro problema para el cual tenemos una cantidad significativa de datos de nuestra red es que los ataques a las aplicaciones se están volviendo mucho más sofisticados con el tiempo. El atacante pasa días realizando tareas de reconocimiento para determinar los detalles de las API, la aplicación, la infraestructura subyacente y el tipo de sistema operativo observando las firmas HTTP/TCP, etc. Los enfoques tradicionales basados en reglas y firmas tienen una utilidad muy limitada en estas situaciones y decidimos continuar con nuestro enfoque basado en IA para aprender automáticamente el comportamiento del usuario y aplicar el comportamiento bueno frente al malo.

Aprendizaje automático para la elaboración de perfiles de comportamiento

La mayoría de las aplicaciones tienen ciertos flujos de trabajo (secuencia de API) y contexto (datos dentro de las API) para los cuales se diseñan diferentes casos de uso/implementaciones que normalmente siguen los usuarios de las aplicaciones. Explotamos estas propiedades y entrenamos nuestros algoritmos de aprendizaje automático para modelar patrones de comportamiento “válidos” en una interacción típica del usuario con la aplicación.

Nuestra ruta de datos muestrea solicitudes/respuestas para cada API junto con los datos asociados y las envía a nuestro motor de aprendizaje central como se muestra en la Figura 3. Este motor genera y actualiza continuamente el modelo de patrones de comportamiento válidos que luego utiliza el motor de inferencia que se ejecuta en la ruta de datos para alertar o bloquear comportamientos sospechosos.

límites de malla 3
Figura 3: Interacción entre Learning Core y los motores de inferencia distribuida

El motor de aprendizaje analiza muchas métricas, como la secuencia de API, las brechas entre solicitudes, las solicitudes repetidas a las mismas API, las fallas de autenticación, etc. Estas métricas se analizan para cada usuario y de forma agregada para clasificar el comportamiento bueno y malo. También realizamos agrupamiento de comportamientos para identificar múltiples secuencias diferentes de “buen comportamiento”. Tomemos un ejemplo para ilustrar esto:

  • El modelo realiza un análisis de muchos usuarios para definir una secuencia de buen comportamiento. Cada color representa diferentes llamadas API individuales:
límites de malla 4
Figura 4: Secuencia normal de API

    El sistema marcará la siguiente secuencia de API como comportamiento sospechoso o malo, que será mitigado automáticamente por el sistema o generará una alerta para que intervenga un administrador.

límites de malla 5
Figura 5: Secuencia sospechosa de API

Cuando pusimos este sistema en producción hace más de un año, hemos ido perfeccionando el modelo en función del uso y los comentarios de los clientes. Hemos podido identificar con éxito los siguientes tipos de ataques: 

  • Rastreadores/escáneres que realizan reconocimiento de una aplicación para encontrar vulnerabilidades y también para crear un mapa de todas las API expuestas por la aplicación.
     
  • Actividad maliciosa sostenida mediante el lanzamiento de múltiples vectores de ataque a API vulnerables
     
  • Ataque de denegación de servicio a nivel HTTP que provoca el agotamiento de los recursos (por ejemplo, múltiples intentos de iniciar sesión en las API)
     
  • Fuga de datos por parte de bots diseñados para extraer información (por ejemplo, información de precios de un sitio de comercio electrónico de la competencia)
     
  • Ataques de fuerza bruta: ataques de diccionario para nombres de usuario y contraseñas
     
  • Identificación de bots buenos (por ejemplo, Google, rastreador de Bing)

Dicho esto, también nos dimos cuenta de que este enfoque tiene algunos problemas: no puede descubrir ataques lentos y de baja intensidad (fuerza bruta, denegación de servicio de la aplicación, escáner) para los cuales necesitamos aplicar técnicas de detección de anomalías.

Detección de anomalías basada en algoritmos e inteligencia artificial

A veces, vemos ataques altamente sofisticados que utilizan grandes botnets distribuidas que pasan desapercibidas para nuestra técnica de análisis de comportamiento. Ejemplos de tales ataques son: 

  • Ataque de fuerza bruta distribuido
  • Ataques distribuidos de apropiación de cuentas basados en diccionarios
  • Escáner distribuido para encontrar vulnerabilidades y explotarlas desde múltiples clientes
  • Ataque DoS HTTP desde una botnet altamente distribuida
  • Botnet que ataca a un pequeño subconjunto de API con un alto consumo de recursos
  • Botnet que ataca un gran conjunto de API con gran cantidad de datos para agotar los recursos

Dado que nuestra ruta de datos de red recopila información de cada nodo de nuestra red global, resulta relativamente fácil realizar análisis de las métricas agregadas de una aplicación en particular, como la tasa de solicitud, la tasa de error, el rendimiento de respuesta, etc. Este análisis nos permite detectar ataques distribuidos y mitigarlos (en cada nodo) identificando los usuarios que podrían formar parte de dichas botnets. Tomemos un ejemplo en el que intentamos detectar anomalías en diferentes ventanas de tiempo (últimos 5 minutos, 30 minutos, 4 horas, 24 horas) al observar las tasas de solicitud y, si la tasa de solicitud es alta dentro de una ventana de tiempo determinada, el sistema realizará el siguiente análisis más profundo de los registros de acceso: 

  • Analizar si la dispersión de la dirección IP de origen es mayor o menor de lo típico. Si las solicitudes provienen de una gran cantidad de IP de origen únicas, esto indica un ataque altamente distribuido que activará una versión más agresiva del análisis del comportamiento del usuario en cada IP de origen.
  • Ejecute una versión más agresiva del análisis del comportamiento del usuario en cada una de las direcciones IP de origen para asignar puntajes de sospecha y tomar las acciones de mitigación configuradas.
  • Si la mayoría de las solicitudes se dirigieron a una cantidad menor de puntos finales de API (de lo habitual), esto indica un ataque de fuerza bruta o un ataque DoS. Si la propagación de APIEP fue mayor de lo habitual, indica un rastreador distribuido, un escáner o un ataque DoS.

Si bien la detección de anomalías siempre ha sido una técnica importante para la detección y prevención de intrusiones (IDS/IPS) en dispositivos de firewall, estos dispositivos no pueden mitigar los ataques globales a la capa de aplicación. Gracias a nuestra capacidad de realizar marcado y aprendizaje de API en toda nuestra plataforma global, ahora podemos suprimir los ataques en la fuente a lo largo de nuestra red distribuida.

Beneficios del aprendizaje automático para la seguridad de aplicaciones y redes

Si bien estábamos extremadamente satisfechos con nuestra implementación de confianza cero basada en una malla de servicios y una puerta de enlace API, nos dimos cuenta de que no era integral para proteger los clústeres de aplicaciones distribuidas de vulnerabilidades y ataques maliciosos. Tuvimos que ampliarlo con aprendizaje automático para el análisis de comportamiento + detección de anomalías junto con técnicas tradicionales basadas en reglas y firmas para brindar una mejor solución de seguridad.

Hemos visto tres ganancias significativas a partir de la incorporación de inferencias distribuidas en nuestra ruta de datos de red L3-L7+ junto con el núcleo de aprendizaje que se ejecuta en nuestro SaaS centralizado: 

  1. Red de confianza cero de extremo a extremo : ahora tenemos la capacidad de aplicar la microsegmentación a nivel de API en toda la plataforma (100 % sin brechas); toda la red es un proxy distribuido globalmente con acceso a nivel de API y acceso a nivel de red cero.
     
  2. Reducción de falsos positivos (en >82%) gracias a la capacidad de ajustar continuamente nuestros modelos, hemos reducido significativamente la cantidad de falsos positivos con los que tienen que lidiar nuestros equipos NOC y SOC. Esta era una gran preocupación con las herramientas tradicionales dada la cantidad de alarmas que generaban, lo que las hacía completamente inútiles.
     
  3. Reducción significativa de la latencia y la utilización del cómputo al migrar lentamente más tareas que se realizaban mediante reglas tradicionales y algoritmos basados en firmas a nuestro nuevo núcleo de aprendizaje automático.

La seguridad de la red y de las aplicaciones es un camino sin fin y parece que aún tenemos un largo retraso en la incorporación de nuevas funciones. Volveremos en un futuro próximo para compartir información adicional sobre los algoritmos y técnicas incrementales que hemos implementado.

Continuará…

Esta serie de blogs cubrirá diversos aspectos de lo que nos llevó construir y operar nuestro servicio SaaS distribuido globalmente con muchos clústeres de aplicaciones en nubes públicas, nuestros PoP de red privada y sitios de borde. El próximo tema será “Observabilidad en nuestra plataforma distribuida globalmente” (próximamente).