Dies ist der vierte Blog in einer Reihe von Blogs, die verschiedene Aspekte dessen behandeln, was für den Aufbau und Betrieb unseres SaaS- Dienstes erforderlich war:
Im vorherigen Blog haben wir Einblicke in die Herausforderungen gegeben, die der Einsatz kryptografischer Techniken zur Sicherung unserer Plattform (Infrastruktur, Apps und Daten) mit sich bringt. In diesem Blog geht es um Techniken, mit denen wir die Plattform vor gezielten Angriffen aus dem Netzwerk schützen – sowohl aus dem Internet als auch von innen. Da Apps nicht mehr auf einen physischen Standort beschränkt sind, sind herkömmliche Perimeter-basierte Firewalls und signaturbasierte Sicherheitslösungen nicht mehr wirksam. Wir erläutern die Mängel unserer anfänglichen Zero-Trust-Sicherheitsimplementierung und erklären, warum und wie wir sie mit Techniken des maschinellen Lernens und Algorithmen erweitert haben, um unsere verteilte Infrastruktur und App-Cluster angemessen zu sichern.
Unsere Plattform betreibt eine große Anzahl von Apps über mehrere Teams hinweg, die ihre eigenen Cluster in Edge, unserem globales Netzwerk und den öffentlichen Clouds von AWS und Azure betreiben. Während die Mehrheit der Workloads aus mit Kubernetes orchestrierten Microservices besteht, verfügen wir über eine Handvoll sehr großer Monolithen (z. B. Elasticsearch), die wir mit Terraform verwalten. Abbildung 1 zeigt die verteilte Natur unserer Plattform. Beispielsweise betreiben wir in jedem unserer über 18 globales Netzwerk -PoPs (mit einigen Dutzend bis etwas über Hundert physischen Servern) Tausende von App-Pods. Am Rand verfügen wir jedoch heute über individuelle Kundenbereitstellungen mit über 3.000 aktiven Standorten (jeder mit ein bis sieben Computern), auf denen einige Dutzend App-Pods laufen.
Die Plattform ist vollständig mandantenfähig, wobei auf jedem Knoten Arbeitslasten von unterschiedlichen Kunden (und unseren eigenen) ausgeführt werden. Da einige dieser Apps dem öffentlichen Internet zugänglich sind, müssen wir sicherstellen, dass die gesamte Kommunikation zu/von den Apps gesichert ist. Wie wir in den beiden vorherigen Blogs beschrieben haben, haben wir zusammen mit unserem eigenen L3-L7+-Netzwerkdatenpfad (VoltMesh) ein robustes Identitäts-, Authentifizierungs- und Autorisierungssystem aufgebaut, das zum Betrieb unseres Service-Mesh und API-Gateways verwendet wird. Wie in Abbildung 2 dargestellt, konnten wir dadurch Transportsicherheit über App-Cluster hinweg (mTLS), von Benutzern (TLS/mTLS) und Mitarbeitern (mTLS) sowie eine auf Authentifizierung und Autorisierung basierende Zugriffskontrolle bereitstellen.
Diese Zero-Trust-Implementierung bietet zwar viele Vorteile, löst jedoch nicht automatisch mehrere Sicherheitsprobleme:
Während der letzten 2,5 Jahre der Entwicklung dieser Plattform haben wir außerdem festgestellt, dass unsere Entwickler häufig Open-Source-Apps integrieren, sie in Container packen und unser DevOps-Team bitten, sie auf der Plattform bereitzustellen. Allerdings fehlen ihnen oft Details zu Interaktionen auf API-Ebene innerhalb dieser Apps, die unser Sicherheitsteam benötigt, um Richtlinien zum Whitelisting der Kommunikation zu erstellen. Dies stellt ein großes Hindernis für die Implementierung unserer Zero-Trust-Sicherheit dar, da es Whitelist-Richtlinien erfordert, die nur von den Apps verwendete APIs zulassen und den gesamten anderen Datenverkehr blockieren. Immer wenn wir Ausnahmen von dieser Anforderung machten, blieben bei einigen Apps nur sehr grundlegende Segmentierungen auf Netzwerkebene übrig, was die Angriffsfläche vergrößerte.
Daher mussten wir unsere vorhandene Zero-Trust-Sicherheitslösung um zusätzliche Sicherheitsfunktionen erweitern, um die oben aufgeführten Probleme zu beheben. Wir haben eine Liste zusätzlicher Sicherheitsfunktionen erstellt, die wir in die Plattform integrieren mussten:
Wir haben uns entschieden, zur Lösung dieser Probleme eine Kombination aus traditionellen signaturbasierten Techniken, statistischen Algorithmen und dynamischeren Ansätzen des maschinellen Lernens zu verwenden. Dies erforderte von uns Änderungen an unserem SaaS-Backend sowie das Hinzufügen neuer Funktionen in unserem Netzwerkdatenpfad.
Um die Plattform zu sperren, erlauben wir nur Netzwerkverbindungen basierend auf der Whitelist der APIs für jede App. Dies erfordert, dass unser Sicherheitsteam mit den Entwicklern koordiniert wird und sicherstellt, dass unsere programmierbare Richtlinien-Engine mit den richtigen API-Informationen versorgt wird. Wir erkannten schnell, dass es für unsere Entwickler unmöglich war, diese Informationen für Apps bereitzustellen, die nicht mit unserem Service-Framework erstellt wurden.
Da sich unser Service-Mesh-Proxy im Netzwerkpfad jedes Zugriffs auf die App befindet, haben wir uns entschieden, die von der App bereitgestellten APIs und statischen Ressourcen kennenzulernen, indem wir eine Laufzeitanalyse jedes Zugriffs durchführen, der über den Proxy erfolgt. Die Herausforderung bei diesem Ansatz besteht darin, API-Endpunkte durch die Überprüfung von URLs zu identifizieren und dynamisch generierte Komponenten herauszufiltern. Beispielsweise sieht der Proxy für eine API „api/user/<user_id>/vehicle/“ Zugriffe wie:
Es kann Millionen solcher Anfragen geben, was die Entschlüsselung äußerst schwierig macht. Die Identifizierung dynamischer Komponenten in diesen zugehörigen Anfragen erfolgt daher mithilfe von Deep Learning und Graphenanalyse. Wir stellen den gesamten URL-Komponentensatz als Diagramm dar und führen dann eine Diagrammclusterung durch, um Unterdiagramme mit ähnlichen Eigenschaften zu finden. Dazu verwenden wir Feature-Sets, die bestimmte Eigenschaften dynamisch generierter Komponenten erfassen, wie z. B.:
Als Ergebnis werden die dynamischen Komponenten klassifiziert und die Ausgabe des Systems sieht wie folgt aus:
Mithilfe dieses maschinellen Lernens von APIs können wir einfach und automatisch eine Richtlinie generieren, die von unserem Service-Mesh-Proxy erzwungen werden kann. Basierend auf den erkannten API-Endpunkten erfahren wir auch andere Eigenschaften, etwa welche Apps welche APIs verwenden, um mit anderen Apps zu kommunizieren, das typische Verhalten dieser APIs usw. Auf diese Weise können wir ein Servicediagramm erstellen, mit dem unser Sicherheitsteam die Interaktion zwischen Diensten für Forensik, Erkennung und Mikrosegmentierung auf API-Ebene visualisieren kann.
Bevor wir mit dem Hinzufügen der beiden verbleibenden Funktionen (Anomalieerkennung und Verhaltensprofilierung) begannen, wollten wir prüfen, ob vorhandene Lösungen uns dabei helfen könnten. Zwar gibt es auf dem Markt zahlreiche Perimeter-Firewalls und Web-App-Firewall-Produkte, die Mehrheit dieser Lösungen ist jedoch auf den Schutz internetbasierter Apps ausgerichtet. Sie gehen davon aus, dass es sich bei dem verarbeiteten Datenverkehr um Web-Datenverkehr handelt, und bieten gezielten Schutz für HTML, JavaScript, SQL, CMS usw. – wodurch das Schreiben von Signaturen und Regeln zum Aufspüren von Schwachstellen und bekannten Exploits relativ einfacher wird.
Obwohl diese Funktion für unseren Web-Verkehr wichtig ist, müssen wir in unserer Umgebung auch eine wachsende Menge an API- und Machine-to-Machine-Verkehr verarbeiten. Um dieses Problem zu lösen, müsste unser Sicherheitsteam anwendungsspezifische Regeln schreiben, die nicht unter bekannte typische Webregeln (wie OWASP CRS) fallen. Normalerweise wissen Sicherheitsadministratoren wenig über die Apps und angesichts der dynamischen Natur der Umgebung wird es noch schwieriger, den Überblick über die App-Typen und -Struktur zu behalten, um diese app-spezifischen Regeln zu schreiben. Obwohl unser Plattformteam diese Funktion in unserem Netzwerkdatenpfad bereitstellt, wird sie von unserem Sicherheitsteam nicht oft verwendet.
Ein weiteres Problem, zu dem uns in unserem Netzwerk zahlreiche Daten zur Verfügung stehen, besteht darin, dass App-Angriffe mit der Zeit immer ausgefeilter werden. Der Angreifer verbringt Tage mit der Aufklärung, um anhand von HTTP-/TCP-Signaturen usw. die Einzelheiten der APIs, der App, der zugrunde liegenden Infrastruktur und des Betriebssystemtyps zu ermitteln. Herkömmliche signatur- und regelbasierte Ansätze sind in diesen Situationen nur von sehr begrenztem Nutzen und wir haben uns entschieden, unseren KI-basierten Ansatz beizubehalten, um das Benutzerverhalten automatisch zu erlernen und gutes von schlechtem Verhalten abzugrenzen.
Die meisten Apps verfügen über bestimmte Arbeitsabläufe (API-Abfolge) und Kontexte (Daten innerhalb der APIs), für die verschiedene Anwendungsfälle/Bereitstellungen konzipiert sind und die normalerweise von den Benutzern der Apps befolgt werden. Wir nutzen diese Eigenschaften und trainieren unsere Algorithmen für maschinelles Lernen, um „gültige“ Verhaltensmuster in einer typischen Benutzerinteraktion mit der App zu modellieren.
Unser Datenpfad erfasst Anfragen/Antworten für jede API zusammen mit den zugehörigen Daten und sendet sie an unsere zentrale Lern-Engine, wie in Abbildung 3 dargestellt. Diese Engine generiert und aktualisiert kontinuierlich das Modell gültiger Verhaltensmuster, das dann von der im Datenpfad ausgeführten Inferenz-Engine verwendet wird, um vor verdächtigem Verhalten zu warnen bzw. es zu blockieren.
Die Lern-Engine betrachtet viele Metriken wie die Reihenfolge der APIs, Lücken zwischen Anfragen, wiederholte Anfragen an dieselben APIs, Authentifizierungsfehler usw. Diese Kennzahlen werden für jeden Benutzer und auf aggregierter Basis analysiert, um gutes von schlechtem Verhalten zu unterscheiden. Wir führen auch eine Verhaltensclusterung durch, um mehrere unterschiedliche Sequenzen „guten Verhaltens“ zu identifizieren. Sehen wir uns zur Veranschaulichung ein Beispiel an:
Die folgende API-Sequenz wird vom System als verdächtiges/schlechtes Verhalten gekennzeichnet, das vom System automatisch gemildert wird oder eine Warnung für einen Administrator generiert, der eingreifen kann.
Seit wir dieses System vor über einem Jahr in Produktion gebracht haben, haben wir das Modell auf der Grundlage von Nutzung und Kundenfeedback kontinuierlich verfeinert. Folgende Angriffsarten konnten wir erfolgreich identifizieren:
Allerdings haben wir auch festgestellt, dass dieser Ansatz einige Probleme mit sich bringt: Er kann keine einfachen und langsamen Angriffe (Brute-Force, App-Denial-of-Service, Scanner) aufdecken, für die wir Techniken zur Anomalieerkennung anwenden müssen.
Manchmal beobachten wir äußerst raffinierte Angriffe, bei denen große, verteilte Botnetze zum Einsatz kommen, die von unserer Technik zur Verhaltensanalyse nicht entdeckt werden. Beispiele für solche Angriffe sind:
Da unser Netzwerkdatenpfad Informationen von jedem Knoten in unserem globales Netzwerk sammelt, ist es relativ einfach, Analysen der aggregierten Kennzahlen einer bestimmten App durchzuführen, beispielsweise Anforderungsrate, Fehlerrate, Antwortdurchsatz usw. Mithilfe dieser Analyse können wir verteilte Angriffe erkennen und (an jedem Knoten) abschwächen, indem wir die Benutzer identifizieren, die Teil solcher Botnetze sein könnten. Nehmen wir ein Beispiel, bei dem wir versuchen, Anomalien in verschiedenen Zeitfenstern (letzte 5 Min., 30 Min., 4 Std., 24 Std.) zu erkennen, indem wir uns die Anforderungsraten ansehen. Wenn die Anforderungsrate in einem bestimmten Zeitfenster hoch ist, führt das System die folgende ausführlichere Analyse der Zugriffsprotokolle durch:
Während die Anomalieerkennung schon immer eine wichtige Technik zur Erkennung und Verhinderung von Angriffen (IDS/IPS) in Firewall-Geräten war, sind diese Geräte nicht in der Lage, globale Angriffe auf Anwendungsebene abzuschwächen. Dank unserer Fähigkeit, API-Markup und -Lernen auf unserer globalen Plattform durchzuführen, sind wir nun in der Lage, Angriffe in unserem verteilten Netzwerk an der Quelle zu unterdrücken.
Obwohl wir mit unserer Zero-Trust-Implementierung auf Basis von Service Mesh und API-Gateway äußerst zufrieden waren, stellten wir fest, dass sie nicht ausreichte, um verteilte App-Cluster vor Schwachstellen und böswilligen Angriffen zu schützen. Um eine bessere Sicherheitslösung bereitzustellen, mussten wir es neben herkömmlichen signatur- und regelbasierten Techniken durch maschinelles Lernen zur Verhaltensanalyse und Anomalieerkennung erweitern.
Durch das Hinzufügen verteilter Inferenzen in unserem L3-L7+-Netzwerkdatenpfad zusammen mit dem Lernkern, der in unserem zentralisierten SaaS ausgeführt wird, haben wir drei wesentliche Vorteile erzielt:
Die Netzwerk- und App-Sicherheit ist eine nie endende Herausforderung und es sieht so aus, als hätten wir noch einen großen Rückstand bei der Anzahl der hinzuzufügenden neuen Funktionen. Wir werden in naher Zukunft darauf zurückkommen, um weitere Einblicke in die inkrementellen Algorithmen und Techniken zu geben, die wir implementiert haben.
In dieser Blogserie werden verschiedene Aspekte dessen behandelt, was für den Aufbau und Betrieb unseres weltweit verteilten SaaS-Dienstes mit vielen App-Clustern in öffentlichen Clouds, unseren privaten Netzwerk-PoPs und Edge-Sites erforderlich war. Als Nächstes folgt „Beobachtbarkeit auf unserer global verteilten Plattform“ (in Kürze verfügbar) …