Sie sind an Cloud Computing interessiert? Legen Sie jetzt los

Analyse von Risiken durch eine fehlerhafte Nutzerauthentifizierung bei JSON Web Token

Nitzan Namer

Verfasser

Nitzan Namer

June 07, 2023

Nitzan Namer

Verfasser

Nitzan Namer

Nitzan Namer ist Sicherheitsforscher bei Akamai.

Kontoübernahme, Berechtigungseskalation und Datenlecks sind drei große potenzielle Risiken, denen JWT-Nutzer und -Unternehmen ausgesetzt sind, wenn sie ein JWT als bevorzugtes Token in einer API auswählen.

Zusammenfassung

  • Forscher von Akamai haben JSON Web Tokens (JWTs) als Vektor für Angriffe durch fehlerhafte Nutzerauthentifizierung, die das Open Web Application Security Project (OWASP) als eine der zehn größten API-Schwachstellen identifiziert hat, analysiert und verschiedene Szenarien aufgedeckt, in denen JWT-Risiken und -Trends eine Rolle spielen. 

  • JWTs sind für die Sicherung von APIs verantwortlich, denn Sie stellen Tokens (in der Regel zwischen Clients und Servern) zur sicheren Verifizierung von Nutzern aus. Diese Tokens sind eines der am häufigsten verwendeten Verifizierungsformate und enthalten Informationen, die in Form von JSON-Objekten geteilt werden.  

  • Obwohl nicht jedes Token verschlüsselt ist, ist es kodiert und trägt eine Verifizierungssignatur. Wir haben einige der vielen Risiken für JWTs untersucht, die auf unsachgemäße Umsetzung oder geringe Entropie und kurze Geheimschlüssel zurückzuführen sind.  

  • Kontoübernahme, Berechtigungseskalation und Datenlecks sind drei große potenzielle Risiken, denen JWT-Nutzer und -Unternehmen ausgesetzt sind, wenn sie ein JWT als bevorzugtes Token in einer API auswählen. Wir haben in unserem Traffic beobachtet, dass die meisten JWTs einen symmetrischen Algorithmus verwenden, obwohl dieser theoretisch weniger sicher ist.

  • In diesem Beitrag zeigen wir Best Practices für den Umgang mit diesen JWT-Risiken auf.

Einführung

JWTs sind ein weit verbreitetes, relativ einfach zu implementierendes Tokenschema, das viele Risiken birgt. Diese Risiken müssen bei der Umsetzung und Sicherung von JWT berücksichtigt werden. Eines der größten Risiken für JWT, das auch zu den zehn größten API-Schwachstellen laut OWASP zählt, ist eine fehlerhafte Nutzerauthentifizierung. 

Eine fehlerhafte Nutzerauthentifizierung tritt auf, wenn eine API die Zugangsdaten und die Identität des Nutzers, von dem die Anfrage stammt, nicht richtig überprüft. Leider handelt es sich hierbei um eine häufig bei JWTs beobachtete Schwachstelle. Diese kann dazu führen, dass ein Angreifer das Konto eines anderen Nutzers nachahmt oder darauf zugreift, was zu einer Berechtigungseskalation und Datenlecks führen kann.

Die Pipeline schützen

Ein JWT ist ein Authentifizierungstoken, das häufig in APIs und Webanwendungen verwendet wird. Wir haben in unserem Traffic beobachtet, dass Webanwendungen mehr APIs verwenden und sie Kunden zugänglich machen, wodurch sich die Notwendigkeit einer nahtlosen Authentifizierung an verschiedenen API-Endpunkten erhöht. 

Die API ist die wichtigste Pipeline eines Unternehmens, die die Authentifizierungs- und Autorisierungsmechanismen enthält, Datenbanken abfragt und den Zugang zu den meisten Funktionen des Unternehmens bereitstellt. Aus diesem Grund sind JWT-Risiken im API-Bereich besonders gefährlich. In diesem Blogbeitrag stellen wir die Grundlagen von JWT, sechs Risiken für JWT und Wege, diese Risiken zu bekämpfen, vor.

Die Grundlagen von JWTs

JWT ist ein Format zum Senden signierter JSON-Daten zur Übertragung in Webanwendungen, mobilen Anwendungen und APIs, die meist nur zur Authentifizierung verwendet werden. Die JWT-Struktur besteht aus drei Elementen: Dem Header (auch als JOSE-Header bezeichnet), der Payload und der Signatur, die jeweils durch einen Punkt getrennt sind (Abbildung 1).

  eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOjE2NzYyMTc5NTAsImV4cCI6MTcwNzc1Mzk1MCwiYXVkIjoiYWthbWFpLWJsb2ciLCJzdWIiOiIiLCJjb21wYW55IjoiQWthbWFpIiwidXNlciI6IkFrYW1haS1yZWFkZXIiLCJhZG1pbiI6Im5vIn0.kMPz3Z7BSlBTJKijD8bcrpzTZejX7VCZ77w5oQwJO6I

Abb. 1: Das ist ein Beispiel für die drei Elemente der JWT-Struktur

Header und Payload

Sowohl der Header als auch die Payload sind Base64-codierte, URL-sichere, codierte, IETF-spezifizierte Empfehlungen für Felder (Abbildung 2). „Codiert“ bedeutet, dass nicht direkt mit bloßem Auge lesbar sind, vom Server jedoch leicht decodiert werden können. Damit sollen die Integrität und Usability der Daten und auch die „URL-Sicherheit“ gewährleistet werden. Auf diese Weise gibt es keine sich überlappenden Zeichen, die von Webbrowsern verwendet werden.

Der JOSE-Header wird sowohl für das JWT als auch für die JSON-Webverschlüsselung (JWE) verwendet, bei der es sich im Grunde um ein verschlüsseltes JWT handelt, durch das die häufigsten JWT-Angriffe abgewehrt werden. Das Feld, das die gewählte Tokenmethode angibt, heißt „typ“ (Typ:JWT/JWE). Die Payload kann je nach Implementierung registrierte Felder (die von der Internet Assigned Numbers Authority angefordert werden) oder nutzerdefinierte Felder enthalten.

Der JOSE-Header wird sowohl für JWT als auch für JSON Web Encryption (JWE) verwendet

Abb. 2: Codiertes JWT

Die Signatur

Der Zweck der Signatur besteht darin, das Token zu verifizieren. Das bedeutet, dass der Server das Token erstellt hat und die Daten sich seit der Erstellung nicht geändert haben.

Beim Erstellen der Signatur gibt es zwei wesentliche Schritte:

  1. Das Anwenden eines Verschlüsselungsalgorithmus (z. B. MAC) auf den Header und die Payload, die durch einen Punkt getrennt sind (der Algorithmus verwendet einen Geheimschlüssel)

  2. Das Anwenden eines Hashing-Algorithmus (z. B. SHA256) auf den verschlüsselten Header und die verschlüsselte Payload

Wenn ein JWT verwendet wird, überprüft der Server die Signatur, um das Token selbst zu validieren. (Später in diesem Beitrag erläutere ich die verschiedenen Algorithmen, die zur Validierung verwendet werden.)

JWTs werden in Webanwendungen häufig zur Authentifizierung eingesetzt, da sie (auch in großem Umfang) nutzerfreundlich und einfach zu implementieren sind und die erforderlichen Daten des Servers clientseitig gespeichert werden. Doch obwohl sie eine Signatur tragen, gibt es Risiken im Zusammenhang mit JWT. Das JWT verwendet Nur-Text und jede Implementierung besteht aus verschiedenen Payload-Feldern. Die entsprechende Angriffsfläche ist also sehr groß und es gibt viel Raum für Fehler.

Durch die Untersuchung einiger der häufigsten und interessanteren Bedrohungen, denen JWTs ausgesetzt sind, können wir Schwachstellen und schädliches Verhalten leichter erkennen, Risiken besser reduzierten und die notwendigen Sicherheitsmaßnahmen einsetzen, um uns vor potenziellen Angriffen zu schützen. 

Es ist unser Ziel, Nutzern einen sichereren Ansatz bei der Arbeit mit JWTs zu bieten und Sicherheitsexperten und Administratoren die Tools und Empfehlungen zur Verfügung zu stellen, die Sie für Ihre Due-Diligence-Verfahren benötigen. 

Sechs Risiken für JWTs

1. Der Server darf ein Token ohne Validierung verwenden

Da ein JWT eine Signatur trägt und nicht verschlüsselt ist, muss es vor der Verwendung validiert werden. Im simpelsten Bedrohungsszenario, in dem eine Anwendung überhaupt nicht validiert wird, kann ein Angreifer die Payload bearbeiten (z. B. Berechtigungseskalation), wobei die Signatur unverändert bleibt oder sogar gelöscht wird, um mehr Berechtigungen zu erhalten.

Eine weitere Methode ist die Verwendung des Parameters „alg“ im Header, der den Algorithmus darstellt, der zum Signieren des Tokens verwendet wurde. „None“ ist ein legitimer Wert (und das JWT wird als „ungesichertes JWT“ bezeichnet), sodass jeder das Token problemlos signieren kann. Am Backend gibt es auch eine mögliche Implementierung der JWT-Verifizierung.

Suchen Sie zunächst nach dem Feld „alg“ im Header. Danach verwenden Sie den angegebenen Algorithmus, um das Token zu verifizieren. Der Algorithmus „None“ bedeutet, dass für dieses Token keine Signatur und Verifizierung erforderlich ist. Das Bearbeiten der Payload und des Headers (zu „alg:none“) und die „Selbstsignierung“ (Löschen der Signatur) des Tokens führt zu einem erfolgreichen Angriff.

Beispiel

Abbildung 3 zeigt ein Beispiel für ein decodiertes JWT.

  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ij 
  oxNjU5MjM5MDIyfQ.PrhAp2DUWXoL01_odyLATuzrwn5rMtY1IVsP8y4LH5E
  decoded:
{
  "alg": "HS256",
  "typ": "JWT"
}
.{
  "name": "example name",
  "iat": 1659239022
}

Abb. 3: Beispiel für ein decodiertes JWT

Wir gehen davon aus, dass der API-Endpunkt das Feld „alg“ in der Payload als den für die Validierung gewählten Algorithmus verwendet.

Wir möchten jedoch das JWT bearbeiten (Abbildung 4). Auf diese Weise gelingt es uns, ein gültiges JWT eines anderen Nutzers zu erstellen.

  eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ijo 
  xNjU5MjM5MDIyfQ.
  decoded:
{
  "alg": "none",
  "typ": "JWT"
}
.{
  "name": "other person's name",
  "iat": 1659239022
}

Abb. 4: Bearbeitetes JWT zur Ausnutzung von alg:none.

Best Practice: Es ist ganz einfach: Führen Sie immer eine Validierung mit einem hartcodierten, vordefinierten Algorithmus durch, bevor Sie das Token verwenden. Verwenden Sie den alg-Parameter nicht als Zeiger für den Validierungsalgorithmus.

2. Verwendung desselben privaten Schlüssels für verschiedene Anwendungen

Es gibt viele Unternehmen, die sich bei verschiedenen Anwendungen für eine getrennte Anmeldung entscheiden. Wenn Sie denselben privaten Schlüssel verwenden, wird in beiden Anwendungen ein gültiges Token erstellt, jedoch jeweils mit einer anderen Nutzer-ID. In diesem Fall geht es darum, das Token einer Anwendung zu verwenden, um bei einer zweiten Anwendung eine Anfrage zu stellen und ein Konto (das Sie nicht ausgewählt haben) zu übernehmen (Abbildung 5).

Screenshot: Verwendung des JWT einer zweiten Anwendung Abb. 5: Verwendung des JWT einer zweiten Anwendung in einer anderen Anwendung, was zu einer Kontoübernahme führt

Best Practice: Eine weitere einfache Faustregel lautet: Verwenden Sie beim Trennen von Nutzer-IDs unterschiedliche private Schlüssel.

 3. Verwendung eines schwachen Signieralgorithmus

Es gibt zwei Hauptgruppen von Algorithmen: symmetrische (HSXXX) und asymmetrische (RSXXX,ESXXX,PSXXX). Ein symmetrischer Algorithmus erfordert einen gemeinsamen Geheimschlüssel; ein asymmetrischer Algorithmus erfordert private und öffentliche Schlüssel (Tabelle 1).

Symmetrisch

HSXXX

HMAC + SHA

Relativ schwacher Algorithmus

Verwendet einen gemeinsamen Geheimschlüssel

Asymmetrisch

RSXXX

RSA + SHA

Sicherer Algorithmus

Verwendet private und öffentliche Schlüssel

ESXXX

ECDSA + SHA

Der sicherste Algorithmus der drei

Verwendet private und öffentliche Schlüssel

Tabelle 1: Die beiden wichtigsten Gruppen von Algorithmen

Aus der Perspektive des Angreifers lässt sich ein symmetrischer Algorithmus einfacher durch einen Brute-Force-Angriff ausnutzen, denn es ist nicht erforderlich, öffentliche Schlüssel zu sammeln, und die Datenverarbeitungszeit ist so effizient wie möglich. Wir haben in unserem Traffic beobachtet, dass symmetrische Algorithmen häufiger verwendet werden als  asymmetrische Algorithmen (Abbildung 6).

Theoretisch erfordern symmetrische Algorithmen weniger Berechnungen, sodass sie in großem Maßstab eine bessere Performance als asymmetrische Algorithmen haben.

Screenshot: Umfrage zu JWT-Algorithmen Abb. 6: Eine Umfrage zu JWT-Algorithmen im Traffic von Akamai zeigt, dass symmetrische Algorithmen am häufigsten verwendet werden

Best Practice: Verwenden Sie asymmetrische Algorithmen. Wir empfehlen die Verwendung des ECDSA-Algorithmus, der derzeit (kryptografisch) die sicherste Wahl ist. Ein ordnungsgemäß gesicherter symmetrischer Schlüssel ist akzeptabel, wenn der Geheimschlüssel eine hohe Entropie aufweist und ausreichend lang ist.

4. Die Wahl eines privaten Schlüssels, der kurz ist und/oder eine geringe Entropie aufweist

Ein privater Schlüssel, der kurz ist und/oder eine geringe Entropie aufweist, könnte schnell mithilfe eines Brute-Force-Angriffs geknackt werden. Es gibt eine simple Software zum Knacken von Schlüsseln, die in leistungsstarken Cloudumgebungen mit Graphic Processing Units (GPU) installiert werden kann. Die GPU-Performance wächst rapide und beeinflusst Funktionen zum Knacken von Schlüsseln. Heutigen High-End-Grafikkarten knacken einen Schlüssel fast 2,5-mal schneller als noch vor drei Jahren. 

In Tabelle 2 sehen Sie einen Vergleich, wie viele Tage es vor drei Jahren dauerte und wie viele es heute dauern würde, einen achtstelligen privaten Schlüssel zu knacken (unabhängig von seiner Entropie).

High-End-Grafikkarte


Tage bis zum Knacken des Schlüssels

Vor drei Jahren

10,5 Tage

Heute

4,5 Tage

Tabelle 2: Die Anzahl der Tage bis zum Knacken eines achtstelligen privaten Schlüssels

Ein siebenstelliger privater Schlüssel, der vor ein paar Jahren in etwa 24 Stunden geknackt worden wäre, kann in weniger als 90 Minuten geknackt werden. Der Einzigartigkeit dieses Angriffs liegt darin, dass er offline ausgeführt wird, ohne dass eine Abwehr seitens des Unternehmens möglich ist oder überhaupt jemand bemerkt, dass ein solcher Angriff stattfindet. 

Stellen Sie sich vor, Sie seien ein von einer Regierung unterstützter Angreifer, der dafür ein Orchestrierungssystem erstellt. Wenn er den privaten Schlüssel des JWT kennt, kann der Angreifer ein signiertes Token erstellen und sich als ein anderer Nutzer ausgeben, allein wenn er dessen ID kennt.

Best Practice: Wählen Sie einen langen privaten Schlüssel (mindestens 10 Zeichen) mit hoher Entropie. Wir empfehlen die Verwendung von RSA zum Generieren.

5. Sensible Daten in der Payload eines JWT

JWTs sind Base64-URL-codiert, d. h. die Payload ist nicht verschlüsselt. Das Speichern von DB-Namen, inkrementellen IDs (aller Art) oder beliebigen internen Feldern und Daten eines Servers führt zu einer übermäßigen Datenexposition, die Angreifer bei anderen Angriffsmethoden ausnutzen können (z. B. fehlerhafte Autorisierung auf Objektebene).

Best Practice: Speichern Sie keine sensiblen Daten in einem JWT. Wenn Sie sensible Daten speichern müssen, verwenden Sie JWE.

6. Verwechslung von Schlüsseln

Bei asymmetrischen Algorithmen wird ein privater Schlüssel verwendet, um das JWT (dessen Signatur) zu fälschen. Zur Validierung des JWT wird ein öffentlicher Schlüssel verwendet. Ein Angreifer kann den im Header angegebenen Algorithmus in einen symmetrischen Algorithmus (z. B. HS256) umwandeln und mit dem öffentlichen Schlüssel, den der Server rechtmäßig zur Verifizierung verwendet, eine Signatur erstellen. 

In diesem Szenario verwendet das nicht ordnungsgemäß implementierte Backend den öffentlichen Schlüssel und führt den symmetrischen Algorithmus (wie vom Angreifer im Header angegeben) aus, um das vom Angreifer erstellte JWT erfolgreich zu validieren.

Beispiel

Abbildung 7 zeigt, wie der Server ein neues JWT erstellt und Abbildung 8 veranschaulicht den Prozess der JWT-Validierung des Servers.

Abbildung 7 zeigt den Prozess des Servers zur Erstellung eines neuen JWT Abb. 7: Serverseitige JWT-Erstellung
Abbildung 8 zeigt den JWT-Validierungsprozess eines Servers Abb. 8: Serverseitige JWT-Validierung

Im letzten Teil der Validierung kann aus einem von zwei Gründen (oder aus beiden) ein Fehler im Vergleich auftreten: 

  1. Header und Payload wurden bearbeitet, die Signatur jedoch nicht 

  2. Es gibt eine Fehlkonfiguration des richtigen Algorithmus oder des richtigen Schlüssels

Abbildung 9 zeigt einen Angriff mit Verwechslung der Schlüssel.

JWT-Fälschungsprozess Abb. 9: JWT-Fälschungsprozess eines Angreifers mit Verwechslung von Schlüsseln

Der letzte Schritt: Der Server überprüft das Token mit dem in Abbildung 8 dargestellten Prozess, in dem der Server dem alg-Feld vertraut. Er überprüft das Token, indem er den HS256-Algorithmus mit dem öffentlichen Schlüssel als geheimen Schlüssel ausführt, was genau dem Plan des Angreifers entspricht.

Best Practice: Verwenden Sie vordefinierte Algorithmen zur Validierung und vertrauen Sie nie Nutzereingaben.

Fazit

JWT ist das am häufigsten verwendete Authentifizierungstoken. Es ermöglicht die Verwendung vieler Webanwendungen und APIs während der Authentifizierung, ohne sich regelmäßig anmelden zu müssen. Es gibt jedoch viele Risiken im Zusammenhang mit JWTs, da sie weder verschlüsselt sind, noch sicher implementiert werden. 

  • Das Leistungsvermögen von Computern entwickelt sich rasant. Dadurch sind schwache geheime Schlüssel einem gehörigen Risiko ausgesetzt, da sie innerhalb von Tagen (statt ehemals Jahren) geknackt werden können. Im Falle von JWT kann diese Art von Angriff offline ausgeführt werden, ohne dass ein Unternehmen es überhaupt bemerkt. 

  • Symmetrische Algorithmen sind die häufigste Art von Algorithmen, was es Angreifern umso leichter macht. 

  • Es gibt auch komplexere Bedrohungen, wie z. B. Authentifizierungsangriffe, aber Authentifizierungsangriffe automatisiert durchzuführen, ist für Angreifer schwierig. Einfache JWT-Angriffsvektoren können jedoch automatisiert und massiv angegriffen werden.

Aus diesen (und vielen anderen) Gründen ist es entscheidend, dass die Nutzer sich der Schwachstellen von JWT und der Best Practices im Bereich Sicherheit bewusst sind, die zum Schutz vor potenziellen Angriffen implementiert werden müssen. Wir hoffen, dass diese Analyse als praktischer Leitfaden zum Schutz von JWTs vor fehlerhafter Nutzerauthentifizierung, einer der zehn größten API-Schwachstellen laut OWASP, genutzt wird.



Nitzan Namer

Verfasser

Nitzan Namer

June 07, 2023

Nitzan Namer

Verfasser

Nitzan Namer

Nitzan Namer ist Sicherheitsforscher bei Akamai.