BLOG

Surmonter les limites du Service Mesh pour la sécurité des clusters d'applications distribuées

Vignette d'Ankur Singla
Ankur Singla
Publié le 13 avril 2020

Il s'agit du quatrième blog d'une série de blogs qui couvrent divers aspects de ce qu'il nous a fallu pour créer et exploiter notre service SaaS :

  1. Plan de contrôle pour le PaaS Kubernetes distribué
  2. Service mesh global pour applications distribuées
  3. Sécurité de la plateforme pour les infrastructures, les applications et les données distribuées
  4. Sécurité des application et des réseaux des clusters distribués
  5. Observabilité sur une plateforme distribuée à l'échelle mondiale
  6. Opérations et SRE d'une plateforme distribuée à l'échelle mondiale
  7. Cadre de service Golang pour les microservices distribués

Dans le blog précédent , nous avons fourni des informations sur le défi que représente l’utilisation de techniques cryptographiques pour sécuriser notre plateforme (infrastructure, applications et données). Ce blog traitera des techniques que nous utilisons pour sécuriser la plateforme contre les attaques ciblées provenant du réseau — depuis Internet ainsi que de l’intérieur. Étant donné que les applications ne sont plus limitées à un emplacement physique, les pare-feu traditionnels basés sur le périmètre et les solutions de sécurité basées sur les signatures ne sont plus efficaces. Nous décrirons les lacunes de notre implémentation initiale de sécurité zero-trust et pourquoi + comment nous l'avons augmentée avec l'apprentissage automatique et les techniques algorithmiques pour sécuriser correctement notre infrastructure distribuée + nos clusters d'applications.

TL;DR (Résumé)

  1. Nos exigences de sécurité d'application à application et d'utilisateur à application étaient compliquées par le fait que notre plateforme exécute des centaines de microservices (sur de nombreux clusters Kubernetes) ainsi que quelques applications monolithiques sur plusieurs fournisseurs de cloud (AWS et Azure), notre réseau mondial et des emplacements périphériques.
     
  2. Il nous a également été demandé de créer des processus et de fournir une solution de sécurité réseau + application robuste qui donnait un accès sélectif à l'infrastructure partagée à nos développeurs, à nos équipes d'exploitation, aux développeurs de nos clients, à leurs équipes d'exploitation et à leurs utilisateurs finaux. Cela est devenu encore plus compliqué par le fait que nous devions répondre à des exigences de conformité telles que PCI-DSS, SOC, etc.
     
  3. Bien que nous ayons déjà construit une solution Zero Trust basée sur notre maillage de services mondial et notre passerelle API, elle n'a pas résolu de nombreux problèmes de sécurité comme la vulnérabilité du système, l'épuisement des ressources, les attaques Internet provenant de robots/programmes malveillants et les besoins de quelques services fournissant un accès non authentifié. De plus, il était parfois difficile pour notre équipe secops d’obtenir des informations sur l’API auprès des développeurs, ce qui est essentiel pour un bon déploiement zero-trust qui s’appuie sur des listes blanches d’accès.
     
  4. Pour répondre à ces besoins, notre équipe de plateforme aurait dû soit acheter des services auprès de fournisseurs/fournisseurs de cloud, soit augmenter notre chemin de données L3-L7+ (détaillé ici ) avec des fonctionnalités de sécurité supplémentaires : pare-feu réseau, pare-feu d'application, protection DDoS, gestion des accès privilégiés, etc. Étant donné qu’aucun fournisseur/ fournisseur de cloud existant ne pouvait résoudre ces problèmes avec des outils offrant une politique unifiée, une observabilité et des capacités de découverte d’API automatisées, nous avons dû prendre la décision difficile de nous lancer dans un projet interne pour augmenter notre chemin de données et notre plan de contrôle.
     
  5. Dans le cadre de l'intégration des capacités de sécurité du réseau et des applications dans le chemin de données, nous avons fini par ajouter de nombreuses nouvelles fonctionnalités, ce qui n'a pas encore été réalisé dans aucun chemin de données réseau à ce jour. Nous avons fusionné les capacités de sécurité algorithmique avec l'apprentissage automatique sur le trafic réseau + application ainsi qu'un moteur de politique programmable qui fonctionne sur l'ensemble de la pile : réseau, HTTP et API. Par conséquent, nous sommes désormais en mesure de fournir différentes capacités de sécurité en fonction de l’environnement de déploiement, du modèle de trafic et des besoins de latence. Cela a rendu notre maillage de services mondial plus sécurisé, réduit le nombre de faux positifs pour notre équipe SOC et entraîné une réduction significative de la latence et des ressources de calcul.

Limites du Service Mesh et de l'architecture Zero-Trust

Notre plateforme exécute un grand nombre d'applications au sein de plusieurs équipes qui exploitent leurs propres clusters en périphérie, notre réseau mondial et les clouds publics AWS et Azure. Alors que la majorité des charges de travail sont des microservices orchestrés à l'aide de Kubernetes, nous disposons d'une poignée de monolithes à très grande échelle (par exemple, elasticsearch) que nous gérons à l'aide de Terraform. La figure 1 démontre la nature distribuée de notre plateforme. Par exemple, dans chacun de nos plus de 18 points de présence (PoP) de réseau mondial (avec quelques dizaines à un peu plus d'une centaine de serveurs physiques), nous exécutons des milliers de pods d'applications. Cependant, à la périphérie, nous avons aujourd’hui des déploiements clients individuels avec plus de 3 000 emplacements actifs (chacun avec un à sept calculs) exécutant quelques dizaines de pods d’applications.

limites de maillage 1
Figure 1 : Applications et données distribuées sur la plateforme Volterra

La plateforme est entièrement multi-locataire, chaque nœud exécutant des charges de travail provenant de différents clients (et les nôtres). Étant donné que certaines de ces applications sont exposées à l’Internet public, nous devons nous assurer que toutes les communications vers/depuis les applications sont sécurisées. Comme nous l'avions souligné dans les deux blogs précédents, nous avons construit un système robuste d'identité, d'authentification et d'autorisation ainsi que notre propre chemin de données réseau L3-L7+ (VoltMesh) qui est utilisé pour alimenter notre maillage de services et notre passerelle API . Comme le montre la figure 2, cela nous a permis de fournir une sécurité au niveau du transport sur les clusters d'applications (mTLS), des utilisateurs (TLS/mTLS) et des employés (mTLS), ainsi qu'un contrôle d'accès basé sur l'authentification + l'autorisation.

limites de maillage 2
Figure 2 : Sécurité des transports avec Service Mesh et API Gateway

Bien que cette implémentation de confiance zéro offre de nombreux avantages, elle ne résout pas automatiquement plusieurs problèmes de sécurité :

  1. Vulnérabilité du système — Une application peut être compromise en raison d'une vulnérabilité du système ou d'un employé autorisé mais malveillant. Il doit y avoir un mécanisme pour détecter de telles situations, prendre automatiquement des mesures correctives et alerter nos équipes SRE.
     
  2. Épuisement des ressources — Il existe de nombreuses situations dans lesquelles même un accès client légitime et autorisé peut lentement épuiser les ressources de l’application en raison d’une mauvaise conception. Ces situations peuvent considérablement dégrader les performances pour les autres utilisateurs.
     
  3. Attaques Internet — Étant donné qu’une grande partie de notre infrastructure et de nos applications (et de celles de nos clients) sont directement exposées à l’Internet public, ces ressources sont continuellement attaquées par des utilisateurs malveillants, des robots et des logiciels malveillants. Nous devons détecter et protéger ces ressources contre les attaques par déni de service, volumétriques et par intrusion afin de fournir un bon temps de réponse aux autres utilisateurs.
     
  4. Services non authentifiés — Bien que la majorité des applications nécessitent une authentification (également nécessaire pour la confiance zéro), il existe des cas où une application ne peut pas être restreinte. Par conséquent, ces applications nécessitent une protection supplémentaire à l’aide de solutions basées sur le réseau.

Au cours des 2,5 dernières années de développement sur cette plateforme, nous avons également réalisé que souvent nos développeurs intègrent des applications open source, les conteneurisent et demandent à notre équipe DevOps de les déployer sur la plateforme. Cependant, ils manquent souvent de détails sur les interactions au niveau de l'API au sein de ces applications, dont notre équipe de sécurité a besoin pour créer des politiques visant à mettre sur liste blanche la communication. Il s’agit d’un obstacle majeur pour notre implémentation de sécurité Zero Trust, car elle impose des politiques de liste blanche qui autorisent uniquement les API utilisées par les applications et bloquent tout autre trafic. Chaque fois que nous avons fait des exceptions à cette exigence, certaines applications se sont retrouvées avec une segmentation très basique au niveau du réseau, augmentant ainsi la surface d’attaque.

Renforcement de notre maillage de services Zero-trust

Par conséquent, nous avons dû compléter notre solution de sécurité Zero Trust existante avec des fonctionnalités de sécurité supplémentaires pour gérer les problèmes énumérés ci-dessus. Nous avons identifié une liste de fonctionnalités de sécurité supplémentaires que nous devions intégrer à la plateforme :

  1. Découverte et contrôle des API — Développez la capacité d'apprendre les API dans les applications en cours d'exécution et automatisez la génération de politiques de liste blanche d'applications/API sans dépendre des développeurs
  2. Détection d'anomalies — Capacité à détecter et à protéger contre les comportements anormaux du trafic provenant de tout type de source (utilisateur/application fiable ou non)
  3. Profilage du comportement — Protégez les applications contre l'épuisement des ressources, les attaques d'applications/API (Internet ou depuis le réseau interne) et protégez-vous contre les attaques volumétriques d'Internet vers l'infrastructure et/ou les applications
  4. Journalisation et visualisation — Possibilité de consigner et de tracer tous les accès pour les besoins futurs d'analyse médico-légale et/ou de conformité

Nous avons décidé d’utiliser une combinaison de techniques traditionnelles basées sur la signature, d’algorithmes statistiques et d’approches d’apprentissage automatique plus dynamiques pour résoudre ces problèmes. Cela nous a obligé à apporter des modifications à notre backend SaaS ainsi qu'à ajouter de nouvelles fonctionnalités dans notre chemin de données réseau.

Apprentissage profond pour la découverte et le contrôle des API

Afin de sécuriser la plateforme, nous autorisons uniquement les connexions réseau basées sur la liste blanche des API pour chaque application. Cela nécessite que notre équipe de sécurité se coordonne avec les développeurs et s'assure que notre moteur de politique programmable est alimenté avec les bonnes informations API. Nous avons rapidement réalisé qu’il était impossible pour nos développeurs de fournir ces informations pour les applications qui n’étaient pas créées à l’aide de notre framework de services.

Étant donné que notre proxy de service mesh se trouve dans le chemin réseau de chaque accès à l’application, nous avons décidé d’apprendre les API et les ressources statiques exposées par l’application en effectuant une analyse d’exécution de chaque accès qui passe par le proxy. Le défi avec cette approche est d’identifier les points de terminaison de l’API en inspectant les URL et en séparant les composants générés dynamiquement. Par exemple, pour une API « api/user/<user_id>/vehicle/ », le proxy verra des accès comme :

Il peut y avoir des millions de telles demandes, ce qui les rend très difficiles à déchiffrer. Par conséquent, l’identification des composants dynamiques dans ces requêtes associées est effectuée à l’aide de l’apprentissage profond et de l’analyse graphique. Nous représentons l'ensemble des composants URL sous forme de graphique, puis effectuons un clustering de graphiques pour trouver des sous-graphiques avec des propriétés similaires à l'aide d'ensembles de fonctionnalités qui capturent des propriétés spécifiques de composants générés dynamiquement tels que :

  • Propriétés structurelles
  • Entropie des nœuds
  • Similitude de Jaccard entre différentes parties du graphe
  • Classification simple de chaînes à l'aide de méthodes d'apprentissage en profondeur bien comprises

En conséquence, les composants dynamiques sont classés et la sortie du système ressemble à ceci :

En utilisant cet apprentissage automatique des API, nous pouvons facilement et automatiquement générer une politique qui peut être appliquée par notre proxy de service mesh. Sur la base des points de terminaison d'API découverts, nous apprenons également d'autres propriétés telles que les applications qui utilisent quelles API pour communiquer avec d'autres applications, le comportement typique de ces API, etc. Cela nous permet de créer un graphique de service qui aide notre équipe de sécurité à visualiser l'interaction de service à service pour l'analyse médico-légale, la découverte et la micro-segmentation au niveau de l'API.

Identifier les lacunes des pare-feu

Avant de nous lancer dans l’ajout des deux fonctionnalités restantes (détection d’anomalies et profilage de comportement), nous avons décidé de voir si les solutions existantes pouvaient nous aider. Bien qu'il existe de nombreux pare-feu périmétriques et produits de pare-feu pour applications Web sur le marché, la majorité de ces solutions sont conçues pour protéger les applications connectées à Internet. Ils partent du principe que le trafic traité est du trafic Web et fournissent une protection ciblée pour HTML, JavaScript, SQL, CMS, etc., ce qui facilite relativement l'écriture de signatures et de règles pour détecter les vulnérabilités et les exploits connus.

Bien que cette capacité soit importante pour notre trafic Web, nous devons également gérer une quantité croissante de trafic API et machine à machine dans notre environnement. Pour résoudre ce problème, notre équipe de sécurité devrait rédiger des règles spécifiques aux applications qui ne relèvent pas des règles Web typiques connues (comme OWASP CRS). En général, les administrateurs de sécurité connaissent peu les applications et, compte tenu de la nature dynamique de l’environnement, il devient encore plus difficile de suivre les types d’applications et la structure pour écrire ces règles spécifiques aux applications. Par conséquent, même si notre équipe de plateforme fournit cette capacité dans notre chemin de données réseau, elle n’est pas souvent utilisée par notre équipe de sécurité.

Un autre problème pour lequel nous disposons d’une quantité importante de données provenant de notre réseau est que les attaques d’applications deviennent de plus en plus sophistiquées au fil du temps. L'attaquant passe des jours à effectuer une reconnaissance pour déterminer les détails des API, de l'application, de l'infrastructure sous-jacente et du type de système d'exploitation en examinant les signatures HTTP/TCP, etc. Les approches traditionnelles basées sur les signatures et les règles sont d’une utilité très limitée dans ces situations et nous avons décidé de poursuivre notre approche basée sur l’IA pour apprendre automatiquement le comportement des utilisateurs et appliquer les bons et les mauvais comportements.

Apprentissage automatique pour le profilage comportemental

La plupart des applications ont certains flux de travail (séquence d'API) et contexte (données au sein des API) pour lesquels différents cas d'utilisation/déploiements sont conçus et généralement suivis par les utilisateurs des applications. Nous exploitons ces propriétés et formons nos algorithmes d’apprentissage automatique pour modéliser des modèles comportementaux « valides » dans une interaction utilisateur typique avec l’application.

Notre chemin de données échantillonne les requêtes/réponses pour chaque API ainsi que les données associées et les envoie à notre moteur d'apprentissage central, comme indiqué dans la figure 3. Ce moteur génère et met à jour en permanence le modèle de modèles comportementaux valides qui est ensuite utilisé par le moteur d'inférence exécuté dans le chemin de données pour alerter/bloquer les comportements suspects.

limites de maillage 3
Figure 3 : Interaction entre Learning Core et les moteurs d'inférence distribués

Le moteur d'apprentissage examine de nombreuses mesures telles que la séquence des API, les écarts entre les requêtes, les requêtes répétées aux mêmes API, les échecs d'authentification, etc. Ces mesures sont analysées pour chaque utilisateur et sur une base globale pour classer les bons et les mauvais comportements. Nous effectuons également un regroupement de comportements pour identifier plusieurs séquences différentes de « bon comportement ». Prenons un exemple pour illustrer cela :

  • Le modèle effectue une analyse sur de nombreux utilisateurs pour définir une séquence de bons comportements. Chaque couleur représente des appels d'API différents :
limites-de-maille-4
Figure 4 : Séquence normale des API

    La séquence d'API suivante sera signalée par le système comme un comportement suspect/mauvais qui sera automatiquement atténué par le système ou générera une alerte pour qu'un administrateur intervienne

limites de maillage 5
Figure 5 : Séquence suspecte d'API

Depuis que nous avons mis ce système en production il y a plus d’un an, nous avons continuellement affiné le modèle en fonction de l’utilisation et des commentaires des clients. Nous avons pu identifier avec succès les types d'attaques suivants : 

  • Des robots d'exploration/scanners effectuant une reconnaissance d'une application pour trouver des vulnérabilités et également pour créer une carte de toutes les API exposées par l'application
     
  • Activité malveillante soutenue en lançant plusieurs vecteurs d'attaque sur des API vulnérables
     
  • Attaque par déni de service de niveau HTTP qui conduit à l'épuisement des ressources (par exemple, plusieurs tentatives de connexion aux API)
     
  • Fuite de données par des robots conçus pour récupérer des informations (par exemple, des informations sur les prix d'un site de commerce électronique par des concurrents)
     
  • Attaques par force brute — attaques par dictionnaire pour identifiants/mots de passe
     
  • Identification des bons robots (par exemple Google, robot d'exploration Bing)

Cela dit, nous avons également réalisé que cette approche présente certains problèmes : elle ne peut pas détecter les attaques lentes et de faible intensité (force brute, déni de service d’application, scanner) pour lesquelles nous devons appliquer des techniques de détection d’anomalies.

Détection d'anomalies basée sur l'algorithme et l'IA

Parfois, nous voyons des attaques très sophistiquées qui utilisent de grands botnets distribués qui passent sous le radar de notre technique d’analyse comportementale. Voici quelques exemples de telles attaques : 

  • Attaque par force brute distribuée
  • Attaques de prise de contrôle de compte basées sur un dictionnaire distribué
  • Scanner distribué pour trouver les vulnérabilités et les exploiter à partir de plusieurs clients
  • Attaque HTTP DoS à partir d'un botnet hautement distribué
  • Botnet ciblant un petit sous-ensemble d'API gourmandes en calcul
  • Botnet ciblant un large ensemble d'API gourmandes en données pour épuiser les ressources

Étant donné que notre chemin de données réseau collecte des informations à partir de chaque nœud de notre réseau mondial, il devient relativement facile d'effectuer une analyse sur les mesures globales d'une application particulière, telles que le taux de requête, le taux d'erreur, le débit de réponse, etc. Cette analyse nous permet de détecter les attaques distribuées et de les atténuer (à chaque nœud) en identifiant les utilisateurs qui pourraient faire partie de ces botnets. Prenons un exemple où nous essayons de détecter des anomalies sur différentes fenêtres temporelles (5 dernières minutes, 30 dernières minutes, 4 heures, 24 heures) en examinant les taux de demande et si le taux de demande est élevé dans une fenêtre temporelle donnée, alors l'analyse plus approfondie suivante des journaux d'accès sera effectuée par le système : 

  • Analysez si la répartition de l’adresse IP source est supérieure ou inférieure à la normale. Si les requêtes proviennent d’un grand nombre d’adresses IP sources uniques, cela indique une attaque hautement distribuée qui déclenchera une version plus agressive de l’analyse du comportement des utilisateurs sur chaque adresse IP source.
  • Exécutez une version plus agressive de l’analyse du comportement des utilisateurs sur chacune des adresses IP sources pour attribuer des scores de suspicion et prendre les mesures d’atténuation configurées.
  • Si la plupart des requêtes sont adressées à un nombre plus restreint de points de terminaison d'API (que d'habitude), cela indique une attaque par force brute ou une attaque DoS. Si la propagation de l'APIEP était plus importante que d'habitude, cela indique une attaque distribuée par un robot d'exploration, un scanner ou une attaque DoS

Bien que la détection des anomalies ait toujours été une technique importante pour la détection et la prévention des intrusions (IDS/IPS) dans les dispositifs de pare-feu, ces dispositifs ne sont pas en mesure d’atténuer les attaques globales au niveau de la couche applicative. Grâce à notre capacité à effectuer le balisage et l’apprentissage des API sur notre plateforme mondiale, nous sommes désormais en mesure de supprimer les attaques à la source sur l’ensemble de notre réseau distribué.

Les bénéfices de l'apprentissage automatique pour la sécurité des applications et des réseaux

Bien que nous ayons été extrêmement satisfaits de notre implémentation Zero Trust basée sur un service mesh et une passerelle API, nous avons réalisé qu'elle n'était pas complète pour sécuriser les clusters d'applications distribuées contre les vulnérabilités et les attaques malveillantes. Nous avons dû l’enrichir avec l’apprentissage automatique pour l’analyse du comportement + la détection des anomalies ainsi que les techniques traditionnelles basées sur les signatures + les règles pour fournir une meilleure solution de sécurité.

Nous avons constaté trois gains significatifs grâce à l'ajout d'inférences distribuées dans notre chemin de données réseau L3-L7+ ainsi qu'à l'apprentissage du cœur exécuté dans notre SaaS centralisé : 

  1. Réseau Zero Trust de bout en bout : nous avons désormais la possibilité d'appliquer une micro-segmentation au niveau de l'API sur l'ensemble de la plateforme (100 % sans aucune lacune) : l'ensemble du réseau est un proxy distribué à l'échelle mondiale avec un accès au niveau de l'API et un accès nul au niveau du réseau.
     
  2. Réduction des faux positifs (de > 82 %) grâce à la possibilité d'ajuster en continu nos modèles, nous avons considérablement réduit le nombre de faux positifs auxquels nos équipes NOC et SOC doivent faire face. Il s’agissait d’une préoccupation majeure avec les outils traditionnels étant donné le nombre d’alarmes qu’ils déclenchaient, les rendant totalement inutiles.
     
  3. Réduction significative de la latence et de l'utilisation du calcul en migrant lentement davantage de tâches qui étaient exécutées par des règles traditionnelles et des algorithmes basés sur des signatures vers notre nouveau cœur d'apprentissage automatique.

La sécurité des réseaux et des applications est une piste sans fin et il semble que nous ayons encore un long arriéré de nouvelles fonctionnalités à ajouter. Nous reviendrons dans un avenir proche pour partager des informations supplémentaires sur les algorithmes et techniques incrémentaux que nous avons mis en œuvre.

À suivre…

Cette série de blogs couvrira divers aspects de ce qu'il nous a fallu pour créer et exploiter notre service SaaS distribué à l'échelle mondiale avec de nombreux clusters d'applications dans des clouds publics, nos PoP de réseau privé et nos sites périphériques. La prochaine étape sera « L’observabilité sur notre plateforme distribuée à l’échelle mondiale » (à venir)…