Eine der interessantesten – und eher frustrierendsten – Dinge, die mir im Laufe der Jahre aufgefallen sind, ist der Unterschied zwischen der Sichtweise von Netzwerkingenieuren und Anwendungsentwicklern auf Apps. Wir haben dies an der Art und Weise gesehen, wie Anwendungen in Netzwerkdiagrammen dargestellt werden, und umgekehrt an der Art und Weise, wie Netzwerke in Anwendungsarchitekturdiagrammen dargestellt werden.
Es ist unnötig zu sagen, dass jeder eine sehr vereinfachte Sicht auf den anderen hat.
Das gilt auch für die Sicherheit, deren Funktion beim Schutz nicht nur von Netzwerken und Anwendungen, sondern des gesamten Unternehmens mittlerweile von größter Bedeutung ist. Es ist wichtig, dass Sicherheitsteams über den Tellerrand typischer Architekturdiagramme hinausblicken, um Anwendungen wirklich zu verstehen. Ein erheblicher Prozentsatz (erfolgreicher) Angriffe wird auf der Anwendungsebene ausgeführt. Je länger wir die einzigartigen Merkmale verschiedener Anwendungstypen nicht erkennen, desto länger bleiben diese Anwendungen anfällig.
Im Mittelpunkt der heutigen Diskussion stehen SPAs. Das sind „Single Page Applications“ für alle, die sich fragen, wofür diese spezielle TLA steht.
Eine Single Page Application ist genau das: eine einzelne Webseite, die als Rahmen für alle anwendungsbezogenen Aufgaben dient. Diese Architektur erinnert an die Zeit des Web 2.0 und das Aufkommen von AJAX als Methode zum „Aktualisieren“ einzelner DOM-Elemente (Document Object Model), anstatt die gesamte Seite neu zu laden. Mit dieser Technik konnte die Leistung erheblich verbessert werden. Sie ist der Vorreiter der modernen Single-Page-Anwendung.
Diese Apps spiegeln eher das Verhalten einer mobilen App wider, bei der die Client-Benutzeroberfläche beim ersten Öffnen geladen wird und die Kommunikation mit dem Server nur Daten umfasst. Das bedeutet, dass jeder Aufruf des Servers lediglich Daten enthält und alle Änderungen an der Benutzeroberfläche auf dem Client erfolgen. Dadurch wird die hin- und hergesendete Datenmenge erheblich reduziert, was, wie Sie sich vorstellen können, zu einer besseren Leistung führt. Diese Art von Apps verwenden APIs zum Datenaustausch.
Generell gehen wir davon aus, dass die meisten dieser APIs nach REST-Prinzipien implementiert werden. Das bedeutet, dass jedes Objekt (das im Allgemeinen als an ein einzelnes UI-Element gebunden betrachtet wird) über eine eigene API verfügt, die zum Ausführen von CRUD-Transaktionen (Erstellen, Lesen, Aktualisieren und Löschen) aufgerufen werden kann. Aus Sicherheitsperspektive macht das die Sache etwas einfacher, weil Sie für einen bestimmten API-Aufruf (URI) Daten in bestimmten Formaten erwarten können. Bei den an „/update/product/123“ gesendeten Daten handelt es sich stets um dasselbe serialisierte Objekt, während bei den an „/delete/order/4433“ gesendeten Daten andere serialisierte Objekte vorliegen. Das bedeutet, dass herkömmliche Methoden zum Verknüpfen bestimmter Richtlinien mit bestimmten URIs verwendet werden können, um diese API zu sichern.
Nun können SPAs diesem Muster folgen – oder auch nicht. Neue Verfahren rund um SPAs können und nutzen zur Durchführung von Transaktionen dieselbe API sowie eine traditionellere Funktion-zu-URI-Zuordnung. Bei einem einzelnen URI-Muster-SPA ändert sich der URI nicht – die zwischen den Servern hin und her gesendeten serialisierten Objekte jedoch schon.
Dies erinnert an SOA/XML-Transaktionen, bei denen ein einzelner Endpunkt (URI) zum Aufrufen mehrerer Funktionen verwendet würde. Die Zielfunktion (Endpunkt) war in den serialisierten XML-Daten enthalten oder wurde manchmal in einen benutzerdefinierten HTTP-Header eingefügt. Dieses Modell führte dazu, dass SOA/XML-Gateways erforderlich wurden, die für den Empfang der Anfrage und die Feststellung, welche Funktion aufgerufen wurde, verantwortlich waren, bevor sie diese an den richtigen Endpunkt (Server) weiterleiteten.
Bei SPAs haben Sie möglicherweise mehrere oder nur wenige API-Aufrufe zu tun. In allen Fällen müssen Sie wahrscheinlich Daten in einem bestimmten Format (vielleicht XML, wahrscheinlicher JSON) sichern. Das heißt, Sie müssen sich darüber im Klaren sein, dass Inhalte Risiken bergen. Da einige Daten möglicherweise zum dynamischen Generieren von UI-Elementen (oder zur anderweitigen Manipulation des DOM auf dem Client) verwendet werden, ist es wichtig, bei jeder Übermittlung potenziell schädlichen Code zu suchen und zu zerstören.
Wenn eine einzelne URI zum Datenaustausch für verschiedene Funktionen verwendet wird, funktioniert die herkömmliche Vorgehensweise, Richtlinien an URIs anzuhängen, leider nicht. Tatsächlich kann dies die Sicherheit gefährden, da solche Richtlinien häufig auf die Erwartung bestimmter Nutzlastformate abgestimmt sind. Auch API-Gateways verknüpfen Richtlinien (Routing, Messung, Zugriff) häufig mit einer bestimmten URI. Das bedeutet, dass die Verwendung von nur wenigen URIs (API-Aufrufen) zur Handhabung vieler weiterer Funktionen mit unterschiedlichen Datenformaten die bestehende Sicherheit gefährden kann.
Dies ist ein Beispiel dafür, warum es für Sicherheit und Entwicklung (nicht DevOps, sondern Entwickler) immer wichtiger wird, von der ersten Codezeile bis zur Bereitstellung enger zusammenzuarbeiten. Es gibt Dinge, die Entwickler frühzeitig tun können, um der Sicherheit die Implementierung der richtigen Schutzmaßnahmen zu erleichtern – beispielsweise durch das Einfügen eines HTTP-Headers mit einem Indikator, der die Ausführung der richtigen Richtlinie ermöglicht. Etwas so Einfaches wie „X-Code: ‚order‘“ würde die Anfragen so anreichern, dass Sicherheitslösungen die Daten identifizieren und anschließend auf potenzielle Exploits scannen könnten.
Architektonisch gesehen erfordert dies möglicherweise einen intelligenten L7-Proxy, der den Code extrahieren und die URI umschreiben kann, bevor die Anfrage an die entsprechende Sicherheitslösung (WAF, API Gateway usw.) weitergeleitet wird. Dieser Ansatz funktioniert auch, wenn der intelligente L7-Proxy die Datenformatsprache wie JSON spricht und Entwickler in jeden Austausch einen Code oder Endpunktnamen einfügen, der zum Umschreiben und Weiterleiten an den richtigen Ort verwendet werden kann.
Im Idealfall lässt sich durch die Integration der Sicherheit auf Anwendungsebene in die App selbst das beste Gleichgewicht zwischen Leistung und Sicherheit erreichen. Das ist jedoch nicht immer möglich und manchmal sind kreative architektonische Lösungen erforderlich, um das Sicherheitsziel zu erreichen.
Generell gilt: Änderungen in der Art und Weise, wie Entwickler die verschiedenen Verantwortlichkeiten auf Client und Server verteilen, haben erhebliche Auswirkungen auf die Art und Weise, wie die Anwendungsdienstinfrastruktur mit nachfolgenden Anfragen und Antworten interagiert. Es ist wichtig, dass Sicherheits-, Entwickler- und Anwendungsdienstinfrastrukturteams in den gesamten SDLC eingebunden sind. Auch die Implementierung einer Architekturlösung nimmt Zeit in Anspruch. Wenn Sie es „bis zum Schluss“ aufschieben, vergeuden Sie Tage – oder Wochen oder vielleicht sogar Monate – zusätzliche Zeit bis zur Markteinführung. Oder Sie gehen ohne Sicherheitsdienste auf den Markt, was seine eigenen Risiken (und Konsequenzen) mit sich bringt.
Zusammenarbeit vom ersten Tag der Entwicklung an ist der beste und schnellste Weg, um sicherzustellen, dass Apps verfügbar, schnell und sicher sind, wenn sie in die Produktion gehen.