Seit einiger Zeit beschäftige ich mich mit der spannenden Thematik sicherer Web Authentisierung. Der Themen-Komplex ist riesig und ich werde in weiteren Blog-Posts noch detailiertere Deep Dives in die Themenbereiche von OpenID Connect, JWT, WebAuthn/FIDO 2 und Cookie-Based Session Authentication unternehmen. In diesem Blog-Post möchte ich einige meiner Erkenntnisse in Bezug auf Authentisierung in SPA/API Architekturen zusammenfassen.
Moderne Web Applikationen entfernen sich immer weiter von den klassischen, monolithischen Ansätzen, hin zu Microservices. Auch die klassische Client-Server MVC-Architektur, wird vermehrt durch SPA Frameworks mit Anbindung an REST oder SOAP APIs ersetzt. Der Übergang hin zu solchen Ansätzen bringt sowohl neue Schwierigkeiten wie auch Bedrohungen mit sich, welche unterschiedlich angegangen werden müssen.
Wenn ich verschiedene Webseiten im Netz analysiere, sehe ich jedoch neben den Design-Fehlern spezifisch zu SPAs und API-Anbindung, immer noch dieselben Fehler, welche in klassischen Client-Server MVC-Architekturen gemacht werden. Ich bin noch weit davon entfernt, mir anzumassen, architekturell perfekte Design-Empfehlungen aussprechen. Für das beschäftige ich mich zu wenig lange mit der Thematik. Doch einige der im Internet anzutreffenden Design Fehler sind solch grundlegender Natur, dass sie sehr simpel zu verhindern wären.
Grundlegende Schwierigkeiten
- Session Management:
HTTP wurde im Jahre 1996 finalisiert veröffentlicht und bringt einige Design Fehler mit sich, welche durch zusätzliche Methodiken gehandhabt werden müssen, um eine sichere und stabile Kommunikation im Internet zu gewährleisten. Eine grundlegende Struktur von HTTP ist, dass das Protokoll stateless funktioniert. Jede Anfrage von einem Client an den Server ist komplett unabhängig von der vorherigen. Dies bringt nicht nur Schwierigkeiten bei der Usability mit sich, sondern auch Sicherheitsprobleme. Die Lösung dafür ist ein sicheres Session Management. Dies wird meist mittels Session Cookies gewährleistet. Aus Sicherheitsperspektive ist es jedoch unabdingbar, die Aktionen eines Benutzers über den gesamten Interaction Lifecycle hinweg zu überwachen und aufzuzeichnen. Nur so sind Repudiation Threats hinreichend mitigierbar.
In SPA/API Architekturen wird das Thema Session Management jedoch oft vergessen, was zu Problemen der Verkettung von Logs der Pre-Authentication Phase führt.
2. Abspeichern von Authentication Tokens – die ewigen Pros und Cons:
Nach der Authentisierung müssen Session Cookies, SWT Tokens oder JWT Tokens Client-Seitig sicher abgespeichert werden. Was jedoch als sicheres Abspeichern gilt, ist schwierig zu beantworten. In Frage kommen drei Storages:
- Cookie Storage: Ist ein veralteter Storage und bringt einige Gefahren mit sich, welche durch Cookie Direktiven wie Secure, HttpOnly, SameSite sowie HTTP Header wie CORS richtig abgesichert werden müssen. Ich werde in einem anderen Post detailiert auf die Direktiven eingehen. Cookies werden in allen Aufrufen automatisch mitgesendet. Dies macht sie somit missbrauchbar für CSRF Attacken.
- LocalStorage: Authentication Token welche im LocalStorage abgespeichert werden sind by design mittels SOP geschützt und ein Secure Flag ist deshalb nicht nötig. Der LocalStorage kann jedoch Browser Sessions überdauern, was in verschiedenen Szenarien unsicher ist. Der LocalStorage ist verfügt nicht über Möglichkeiten von HttpOnly Direktiven. Deshalb ist er angreifbar entgegen XSS. Jedoch geben sie einen verbesserten Schutz für CSRF.
- SessionStorage: SessionStorage bringt fast alle Vor- und Nachteile mit sich wie auch LocalStorage. Jedoch mit dem Unterschied, dass er nur für solange gespeichert wird, wie die Browser Session andauert.
Entweder der eine Threat oder der Andere
Je nachdem wo Authentication Tokens gespeichert werden, macht sie also automatisch missbrauchbar für CSRF oder angreifbar für XSS. Viele Empfehlungen gehen in die Richtung, eher Cookies zu verwenden, da CSRF-Angriffe einfacher zu handhaben sind als XSS-Angriffe. Auch ich teile die Meinung, dass mittels SameSite und CSRF-Token Werkzeuge zur Verfügung stehen, um CSRF in den Griff zu bekommen. Jedoch muss man sich auch bewusst sein, dass durch XSS schier unbegrenzte Möglichkeiten auf der Client-Seite möglich sind und der Authentication Token dem Angreifer somit meist egal sein können, wie auch James Kettle, Director of Research bei PortSwigger hier einleuchtend argumentiert. Wie man sich entscheidet, hängt deshalb auch davon ab, welche Bedrohungs-Szenarien für die jeweilige Applikation in Frage kommen. Was uns wieder zum Punkt bringt, dass ein sauberes Threat Modeling unabdingbar ist.
SWT Token Authentication
Viele SPA/API Architekturen verwenden nach der Authentisierung ausschliesslich einen SWT, Simple Web Token für die Authentisierung an der API. Dieser wird dabei meist im Session Storage gespeichert.
Nachteile:
– Die Speicherung im Web Storage macht ihn angreifbar für XSS.
– Ein Tracking der Session über den gesamten Interaction Lifecycle ist darüber nur schwer möglich. Dadurch entstehen verschiedene Repudiation Threats
Vorteile:
– CSRF Attacken sind durch die Speicherung im Web Storage jedoch nicht so einfach möglich, denn der Token muss auf der Client-Seite bewusst, bei jedem gewünschten Request per JavaScript ausgelesen und mitgesendet werden.
– Die Verwendung ist über Cross-Domain Requests einfach implementierbar. Dadurch können auch Microservice Architekturen gut angesteuert werden, welche teils mehrere Sub-Domains verwenden können.
– Machine-to-Machine Authentisierung ist darüber einfach steuerbar, was bei öffentlich zugänglichen APIs vielfach erwünscht ist
JWT Token Authentication
Die Verwendung von JWT Token findet immer breitere Verwendung. Jedoch muss man sich auch bei JWT verschiedener Vor- und Nachteilen bewusst sein.
Nachteile:
– Meistens werden sie im Web Storage gespeichert, was sie angreifbar für XSS macht. Jedoch gibt es über Token Sidejacking Prevention ein Design Pattern, welches einen Diebstahl über XSS überflüssig macht.
– Es gibt mehrere Fallstricke bei der Implementation von JWT, was sie in der Vergangenheit angreifbar machte.
Vorteile:
– Der Session Status wird auf die Client-Seite ausgelagert. Dies führt zu einer besseren Skalierbarkeit für Web Applikationen mit sehr vielen Benutzern. Jedoch müssen frühzeitige Token Invalidierungen auch in einer Tabelle getrackt werden, was wiederum zusätzlicher Aufwand bedeutet.
– Der JSON-Inhalt der JWT Token kann sowohl signiert wie auch verschlüsselt werden. Dadurch können sogenannte Claims in die Tokens geschrieben werden, welche über mehrere Microservices oder 3rd Party Service kryptographisch auf ihre Validität hin überprüft werden können. Dies ist einer der Gründe wieso sie in OAuth2 wie auch OpenID Connect zur Verwendung kommen.
Abschliessend
Wie immer im Leben, bringen alle Architektur-Ansätze ihre Vor- jedoch auch Nachteile mit sich. Die noch so wünschenswerte “One Solution fits all Situations” gibt es somit nicht. Wie immer gilt es abzuwägen, welche Ziele man verfolgt und welche Threats wie mitigiert werden sollen.
Entwickler sollen sich auch bewusst sein, dass alle Sicherheits-Funktionen welche die gängigen Frameworks bieten, auch unsicher implementiert werden können, wenn nicht genau nach Best Practices vorgegangen wird. Hinter vielen Ecken lauern Fallgruben. 😉 Aus diesem Grund empfehle ich, bereits in der Design Phase die OWASP Cheat Sheets zu konsultieren und das Design mit Security Requirements aus dem ASVS zu fundieren.
Ich freue mich bereits auf jede Anmerkung und Ergänzungen zu meinen Erleuterungen.
Comments