Bild von JSON Web Tokens verstehen

25. Jul 2023

JSON Web Tokens verstehen

Einblicke in die Sicherheitsthemen im Webumfeld.

Sicherer Austausch von Informationen zwischen Servern

In der heutigen vernetzten Welt ist die sichere Kommunikation zwischen Servern von entscheidender Bedeutung. Eine wichtige Komponente, um diese Sicherheit zu gewährleisten, sind JSON Web Tokens (JWT). Diese Tokens ermöglichen den sicheren Austausch von Informationen zwischen verschiedenen Servern und tragen zur Gewährleistung der Integrität und Authentizität der Daten bei.

Im Rahmen eines spannenden zweitägigen Workshops haben uns Urs Müller und Mischa Bachmann von der Firma Compass Security detaillierte Einblicke in die Sicherheitsthemen im Webumfeld gegeben. Wir haben bereits einen Blogbeitrag zur Authentifizierung mittels HTTP-Formularen verfasst. Des Weiteren werden wir in einem kommenden Beitrag das Thema OAuth und OpenID behandeln, die ebenfalls zur Verbesserung der Sicherheit von Webanwendungen beitragen.

Nun möchten wir uns in diesem Beitrag genauer mit dem Thema JWT befassen. Wir werden die Struktur von JWT untersuchen, Validierungsmechanismen beleuchten und Best Practices für eine sichere Implementierung vorstellen. Dabei werden wir auch auf die Verbindung zwischen JWT und der Authentifizierung mittels HTTP-Formularen eingehen, um Ihnen ein umfassendes Verständnis für die Sicherheitsaspekte von Webanwendungen zu vermitteln.

JSON Web Token

JWT können in Form von Signed Tokens (JWS) oder Encrypted Tokens (JWE) vorliegen, wobei wenn von einem JWT gesprochen wird meistens ein JWS gemeint ist. Auch ich werde dies verwenden und von nun an von JWT sprechen wenn ich JWS beschreibe.

Struktur des Tokens

Ein JWT besteht aus drei Teilen: dem Header, Payload und der Signatur. Jeder Teil ist Base64-Codiert und durch ein Punkt getrennt aneinander gehängt. Hier ist zu beachten, obwohl es für uns Menschen so aussieht, ist die Base64-Codierung keine Verschlüsselung und kann leicht decodiert werden. Für JWT wird eine URL sichere Version der Base64-Codierung verwendet, oft auch base64url genannt. Damit JWT auch direkt ohne weitere Codierung in eine URL gepackt werden können.

 

Aufbau eines JWT, zusammen mit dem Inhalt des Headers und der Payload.

1. Header

Der Header enthält Metadaten über das Token, wie den verwendeten Signaturalgorithmus und den Token-Typ (immer auf "JWT" gesetzt).

2. Payload

Der Payload enthält die tatsächlichen Daten, die übertragen werden sollen, in Form von Key-Value-Paaren den sogenannten Claims. Einige dieser Claims sind vordefiniert, diese sollten nur für die vordefinierte Funktion verwendet werden. Ein Set von sieben Claims ist auch empfohlen, aber nicht erforderlich, in allen JWT mit einzubauen diese sind:

  • iss (issuer): Der Ersteller des JWT
  • sub (subject): Subject of the JWT (the user)
  • aud (audience): Für wen das JWT bestimmt ist
  • exp (expiration time): Zeit nach dem das JWT nicht mehr gültig ist.
  • nbf (not before time): Zeit vor der das JWT noch nicht gültig ist
  • iat (issued at time): Zeit als das JWT erstellt wurde
  • jti (JWT ID): Unique identifier; kann verwendet werden um Replay Angriffe zu verhindern in dem sichergestellt wir das jeder Token nur einmal verwendet wird.
3. Signatur

Die Signatur wird aus dem Header und der Payload mithilfe des im Header definierten Signaturalgorithmus erstellt und stellt sicher, dass das JWT nicht unerlaubt verändert wurde.

 

Die Signatur wird über den Header und die Payload gemacht.

Signatur

Man kann entweder symmetrische oder asymmetrische Verschlüsselung für die Signatur verwenden. Bei der simpleren und schneller zu berechnender symmetrischer Verschlüsselung haben sowohl der Autorisierungsservice als auch der Service der Applikation den gleichen Schlüssel zur Validierung der Signatur. Bei asymmetrischer Kryptografie hingegen hat der Autorisierungsservice einen privaten Schlüssel für die Signaturerstellung und einen öffentlichen Schlüssel zur Validierung. Es ist wichtig zu beachten, dass bei Kompromittierung eines symmetrischen Schlüssels der Angreifer valide JWT erstellen kann, während dies bei asymmetrischer Verschlüsselung nur möglich ist, wenn der Angreifer Zugriff auf das geheime Passwort des Autorisierungsservers hat. Aus diesem Grund ist die Verwendung asymmetrischer Signatur in den meisten Fällen zu bevorzugen, es sei denn, Autorisierung und Applikation laufen auf demselben Server.

 

Bei der symmetrischen Signierung haben alle ein gemeinsamen Schlüssel, das Shared Secret. Der Server, der das JWT erstellt, verwendet den gemeinsamen Schlüssel, um die Signatur zu erstellen. Alle, die den gemeinsame Schlüssel haben, können jetzt validieren, dass die Signatur mit dem gemeinsamen Schlüssel erstellt wurde. Da aber mehrere den Schlüssel kennen, weiss man nicht, wer die Signatur erstellt hat.
Bei der asymmetrischen Signierung hat der Server, der das JWT erstellt, ein öffentlicher Schlüssel, den alle kennen. Zudem besitzt der Server auch noch ein privaten Schlüssel. Um die Signatur zu erstellen, verwendet der Server seinen Privaten Schlüssel. Mit dem öffentlichen Schlüssel können anschliessend alle überprüfen, dass die Signatur mit dem privaten Schlüssel gemacht wurde. Da nur der Server den Privaten Schlüssel hat, weiss man, dass dieser die Signatur erstellt hat.

Sicherheitsaspekte

Ein JWT gewährleistet durch seine Signatur, dass sowohl der Header als auch die Payload nicht manipuliert wurden. Jedoch ermöglicht es jedem, der Zugriff auf das JWT hat, dieses auszulesen. Wenn ein Schutz gegen Auslesen gewünscht ist, kann ein JWE verwendet werden. Jedoch ist dies normalerweise nur selten nötig, da JWT in der Regel über sichere und verschlüsselte Verbindungen übertragen werden. Es ist jedoch somit wichtig, dass das Token auch sicher im Client, meistens ein Browser, abgelegt ist und keiner anderen als der Zielwebsite zugänglich ist. Daher sollten in einem JWT keine sensiblen Daten wie Passwörter, sondern lediglich Benutzernamen, Rollen oder ähnliches abgelegt werden.

Um die Sicherheit der Signatur zu garantieren, muss die Library, die zur Verarbeitung von JWT verwendet wird, so konfiguriert werden, dass nur der erwartete Signaturalgorithmus erlaubt ist. Wenn ein JWT einen unerwarteten Signaturalgorithmus verwendet, sollte es verworfen werden. Ansonst können möglicherweise valide Tokens generiert werden. Wenn beispielsweise bei einem auf asymmetrischer Signatur basierten Token eine symmetrische Validierung verwendet wird, geht die gesamte Sicherheit verloren, da das Token mit dem öffentlichen Schlüssel signiert werden kann und somit gültig ist, aber jeder Zugriff auf den öffentlichen Schlüssel hat. Selbst wenn man diesen Sicherheitsschritt weglässt sollte man sicherstellen, dass nur sichere Signaturalgorithmen zugelassen sind. Aktuell sind alle im Standard definierte Algorithmen ausser "none" sicher. Der "none" Algorithmus beinhaltet keine Signatur und lässt somit keine Validierung zu. 

 

Bei der “Algorithm Confusion Attack” verwendet ein Angreifer den öffentlichen Schlüssel, des zum Beispiel Login Server, um ein vom Angreifer erstelltes JWT zu signieren. Als Algorithmus für die Signatur nimmt er ein symmetrischen Algorithmus, wobei er als Shared Secret den öffentlichen Schlüssel des Loginservers verwendet. Der Server, der das JWT zugeschickt bekommt, verwendet den im Header des JWT angegebene symmetrische Algorithmus, um die Signatur zu validieren. Da er auch den öffentlichen Schlüssel des Login Server hinterlegt hat, kommt er zum Schluss, dass das JWT valide ist.

 

Um Missbrauch von JWT zu verhindern, zum Beispiel indem ein Benutzer mehr Rechte behält, nachdem sie ihm entzogen wurden, sollte der JWT ein Ablaufdatum im Header enthalten. Die Lebensdauer des Tokens sollte so kurz wie möglich gewählt werden, um sicherzustellen, dass immer die neuesten Benutzeransprüche verwendet werden.

Best Practices

Um die eigene Implementierung zu validieren, kann man die folgenden Schritte prüfen:

  1. Die JWT-Bibliotheken sind alle aktualisiert, um sicherzustellen, dass bekannte Sicherheitslücken geschlossen sind
  2. JWT mit invalider Signatur werden verworfen
  3. JWT, die mit nicht erlaubten Signaturalgorithmen signiert wurden, werden verworfen
  4. Nur der erwartete Schlüssel wird zur Prüfung der Signatur verwendet. Dies ist wichtig dass ein Angreifer nicht sein Schlüssel einspeisen kann
  5. JWT die abgelaufen oder noch nicht gültig sind, werden verworfen

Fazit

JWT können ein wichtiges Tool sein, um einen sicheren und manipulationsresistenten Austausch von Informationen zwischen Servern zu ermöglichen. Damit dies funktioniert, ist es wichtig, einige Schritte einzuhalten. Deine Applikation sollte nur valide JWT akzeptiert, die die von der Applikation erwartete Parameter enthält. Alle anderen sollten verworfen werden. Insbesondere solche, mit unerwarteten Signieralgorithmen. Zudem sollte der Inhalt von JWT nicht durch andere einsehbar sein, sollten sie über einen verschlüsselten Kanal gesendet werden oder alternativ verschlüsselte Tokens (JWE) verwendet werden.

Falls dich das Thema zu Sicherheit im Webumfeld interessiert findest du weitere Informationen in unseren Blogbeitrag Leitfaden zur Authentifizierung mittels http-Formularen


Schliessen
Stamp Icon-Print Icon-Clear
S
M
L
XL
XXL