Was ist, wenn JWT gestohlen wird?


201

Ich versuche, eine zustandslose Authentifizierung mit JWT für meine RESTful-APIs zu implementieren.

AFAIK, JWT ist im Grunde eine verschlüsselte Zeichenfolge, die während eines REST-Aufrufs als HTTP-Header übergeben wird.

Aber was ist, wenn es einen Lauscher gibt, der die Anfrage sieht und den Token stiehlt ? Dann kann er eine Anfrage mit meiner Identität fälschen?

Tatsächlich gilt dieses Problem für alle tokenbasierten Authentifizierungen .

Wie kann man das verhindern? Ein sicherer Kanal wie HTTPS?


1
Aus diesem Grund sind Token oft nur für kurze Zeit gültig. Und ja, Sie sollten HTTPS verwenden, wenn Sie Bedenken hinsichtlich der Vertraulichkeit Ihrer Daten haben.
Jonathon Reinhart

4
@ JonathonReinhart Wenn ein Token jedoch bald abläuft, muss mein Client ein neues Token erhalten, indem er sich von Zeit zu Zeit erneut authentifiziert. Ist es nicht irgendwie langweilig?
smwikipedia

@ JonathonReinhart Ich glaube, ich verstehe, warum Token nur von kurzer Dauer ist. Auf diese Weise muss der Server den Ablauf eines Tokens nicht verfolgen und somit der Skalierbarkeit Platz machen. Es ist eine Art trade-offzwischen having finer control of token expirationund having better scalability.
smwikipedia

2
Kann das auch helfen? - "Ein gängiger Sicherheitsmechanismus zum Erkennen von Token-Diebstahl besteht darin, den Ursprung der IP-Adresse der Anfrage zu verfolgen." - im letzten Abschnitt hier ausführlich beschrieben - firebase.google.com/docs/auth/admin/manage-sessions
Ula

3
Theoretisch ist es unmöglich, Token-Diebstahl zu verhindern. Das Beste, was wir tun können, ist festzustellen, dass dies geschehen ist, und die Sitzung so schnell wie möglich zu widerrufen. Die beste Methode zur Erkennung ist die Verwendung rotierender Aktualisierungstoken (wie von RFC 6819 vorgeschlagen). Hier ist ein Blog, der dies im Detail erklärt: supertokens.io/blog/…
Rishabh Poddar

Antworten:


284

Ich bin der Autor einer Knotenbibliothek, die sich mit der Authentifizierung in einer gewissen Tiefe befasst, Express-Stormpath , daher werde ich hier einige Informationen einbringen .

Zunächst einmal werden JWTs normalerweise NICHT verschlüsselt. Es gibt zwar eine Möglichkeit, JWTs zu verschlüsseln (siehe: JWEs ), dies ist jedoch in der Praxis aus vielen Gründen nicht sehr häufig.

Als nächstes unterliegt jede Form der Authentifizierung (mit oder ohne JWTs) MitM-Angriffen (Man-in-the-Middle). Diese Angriffe treten auf, wenn ein Angreifer IHREN NETZWERK-Datenverkehr ANZEIGEN kann, während Sie Anfragen über das Internet stellen. Dies kann Ihr ISP sehen, die NSA usw.

Dies ist, was SSL verhindert: Durch die Verschlüsselung Ihres NETWORK-Datenverkehrs von Ihrem Computer -> eines Servers bei der Authentifizierung kann ein Dritter, der Ihren Netzwerkverkehr überwacht, Ihre Token, Kennwörter oder ähnliches NICHT sehen, es sei denn, er ist in der Lage um eine Kopie des privaten SSL-Schlüssels des Servers zu erhalten (unwahrscheinlich). Dies ist der Grund, warum SSL für alle Arten der Authentifizierung obligatorisch ist.

Nehmen wir jedoch an, dass jemand Ihr SSL ausnutzen und Ihr Token anzeigen kann: Die Antwort auf Ihre Frage lautet: JA , der Angreifer kann dieses Token verwenden, um sich als Sie auszugeben und Anforderungen an Ihren Server zu stellen.

Hier kommen nun Protokolle ins Spiel.

JWTs sind nur ein Standard für ein Authentifizierungstoken. Sie können für so ziemlich alles verwendet werden. Der Grund, warum JWTs so cool sind, ist, dass Sie zusätzliche Informationen in sie einbetten und überprüfen können, ob niemand damit herumgespielt hat (Signieren).

JWTs selbst haben jedoch nichts mit "Sicherheit" zu tun. In jeder Hinsicht sind JWTs mehr oder weniger dasselbe wie API-Schlüssel: nur zufällige Zeichenfolgen, mit denen Sie sich irgendwo bei einem Server authentifizieren.

Was Ihre Frage interessanter macht, ist das verwendete Protokoll (höchstwahrscheinlich OAuth2).

Die Funktionsweise von OAuth2 besteht darin, dass es Clients vorübergehend temporäre Token (wie JWTs!) Zur Authentifizierung nur für einen KURZEN ZEITRAUM zur Verfügung stellt!

Die Idee ist, dass der Angreifer den gestohlenen Token nur für kurze Zeit verwenden kann.

Bei OAuth2 müssen Sie sich von Zeit zu Zeit erneut beim Server authentifizieren, indem Sie Ihren Benutzernamen / Ihr Kennwort oder Ihre API-Anmeldeinformationen angeben und anschließend ein Token zurückerhalten.

Da dieser Prozess von Zeit zu Zeit stattfindet, ändern sich Ihre Token häufig, was es für Angreifer schwieriger macht, sich ständig als Sie auszugeben, ohne große Probleme zu haben.

Hoffentlich hilft das ^^


3
Der Autor des folgenden Artikels argumentiert, dass ein Nachteil von JWT darin besteht, dass die einzige Möglichkeit, sich von einem gestohlenen JWT zu erholen, darin besteht, ein neues Schlüsselpaar zu generieren und alle Benutzer effektiv abzumelden. Während bei in einer Datenbank gespeicherten Sitzungs-IDs die Website nur die Sitzungen des betroffenen Benutzers löschen und ihn von allen Geräten abmelden konnte. Ich bin mir nicht sicher, wie OAuth2 hier ins Bild passt oder ob es hilft, die dargestellten Nachteile abzumildern. medium.com/@rahulgolwalkar/…
Marcel

4
Der Autor ist falsch. Es gibt verschiedene Entwurfsmuster, mit denen Sie Token ungültig machen können. Aber im Allgemeinen: Die Verwendung eines JWT für Authentifizierungszwecke ist eine schlechte Idee. Es ist weitaus effizienter, ein Sitzungscookie mit einer darin eingebetteten Sitzungsidee zu verwenden, die kryptografisch signiert ist.
rdegges

1
@rdegges Bitte sagen Sie mir, wie schlecht JWT für die Authentifizierung ist. und wie kann ich Sitzungscookies verwenden, die Sie in Ihrem Kommentar oben erwähnt haben?
Noman Tufail

6
Dies ist viel zu lang, um eine einzelne Antwort einzugeben. Wenn Sie mehr erfahren möchten, habe ich einen ausführlichen Vortrag zu diesem Thema gehalten. Sie können meine Folien online überprüfen: Speakerdeck.com/rdegges/jwts-suck-and-are-stupid
rdegges

2
Theoretisch ist es unmöglich, Token-Diebstahl zu verhindern. Das Beste, was wir tun können, ist festzustellen, dass dies geschehen ist, und die Sitzung so schnell wie möglich zu widerrufen. Die beste Methode zur Erkennung ist die Verwendung rotierender Aktualisierungstoken (wie von RFC 6819 vorgeschlagen). Hier ist ein Blog, der dies im Detail erklärt: supertokens.io/blog/…
Rishabh Poddar

31

Ich weiß, dass dies eine alte Frage ist, aber ich denke, ich kann meine $ 0,50 hier fallen lassen, wahrscheinlich kann sich jemand verbessern oder ein Argument liefern, um meinen Ansatz völlig abzulehnen. Ich verwende JWTs in einer RESTful-API über HTTPS (ofc).

Damit dies funktioniert, sollten Sie immer kurzlebige Token ausgeben (abhängig von den meisten Fällen, in meiner App setze ich den expAnspruch tatsächlich auf 30 Minuten und ttlauf 3 Tage, damit Sie dieses Token aktualisieren können, solange ttles noch vorhanden ist gültig und der Token wurde nicht auf die schwarze Liste gesetzt )

Für die authentication service, um zu entkräften Token, wie ich eine in-Memory - Cache - Schicht (verwenden redis in meinem Fall) als JWT blacklist/ ban-listvor, abhängig von einigen Kriterien: (Ich weiß , dass es die RESTful Philosophie bricht, aber die gespeicherten Dokumente sind wirklich kurzlebig, da ich für ihre verbleibende ttlLebenszeit auf die schwarze Liste setze - Behauptung-)

Hinweis: Token auf der schwarzen Liste können nicht automatisch aktualisiert werden

  • Wenn user.passwordoder user.emailaktualisiert wurde (erfordert Passwortbestätigung), Auth - Dienst gibt eine aktualisierte Token und Ungültigmachungseinträge (schwarze Liste) vorhergehende (n), so dass , wenn Ihr Kunde erkennt , dass Identität des Benutzers irgendwie beeinträchtigt wurde, können Sie diesen Benutzer auffordern , das Passwort zu ändern . Wenn Sie die schwarze Liste nicht dafür verwenden möchten, können Sie (aber ich ermutige Sie nicht dazu) den iat(ausgestellten) Anspruch gegen user.updated_atFeld validieren (wenn jwt.iat < user.updated_atdann JWT nicht gültig ist).
  • Benutzer absichtlich abgemeldet.

Schließlich validieren Sie das Token normal, wie es jeder tut.

Hinweis 2: Anstatt das Token selbst (das sehr lang ist) als Cache-Schlüssel zu verwenden, empfehle ich, ein UUID-Token für den jtiAnspruch zu generieren und zu verwenden . Was gut ist und ich denke (nicht sicher, da es mir gerade in den Sinn gekommen ist), dass Sie dieselbe UUID wie das CSRF-Token auch verwenden können, indem Sie ein secure/ non-http-onlycookie damit zurückgeben und den X-XSRF-TOKENHeader mit js ordnungsgemäß implementieren . Auf diese Weise vermeiden Sie den Rechenaufwand, ein weiteres Token für CSRF-Prüfungen zu erstellen.


9
Es ist nie zu spät, Ihre Idee einzubringen. Danke für deine Antwort.
smwikipedia

2
Wenn Sie eine Blacklist auf dem Server speichern, die für jede Anforderung überprüft werden muss, verwenden Sie einfach eine alte Sitzung.
Franklin Yu

@FranklinYu Eine Blacklist ist viel "billiger" als ein vollständiger Session Store. Da Sie kurzlebige Schlüsselwertobjekte speichern (abhängig von der verbleibenden Lebensdauer, die ziemlich kurz sein sollte) und dies nur für Abmeldeaktionen und solche Aktionen geschieht, die Token ungültig machen, ist dies nicht bei jedem Token der Fall gespeichert ofc.
Frondor

2
Wie billig kann es sein? Erstens, wenn Sie noch etwas auf der Serverseite speichern, genießen Sie nicht den von JWT beanspruchten Vorteil der Skalierbarkeit, da es immer noch einen zentralen Blacklist-Server gibt, mit dem der gesamte Anwendungsserver sprechen muss, bevor er etwas unternimmt. Wenn Sie aufgrund des schnellen Ablaufs nur eine 1k-Blacklist speichern müssen, können Sie dies auch für Sitzungen tun und müssen daher nur 1k-Sitzungen speichern.
Franklin Yu

3
Ich mag diesen Ansatz. Sie müssen die Blacklist nicht bei jeder Anforderung überprüfen, sondern nur bei einer Anforderung, die nach Ablauf der JWT (die Sie aus dem Token selbst lesen können) und bis zur TTL-Periode danach erfolgt. In einem "Standard" -Anwendungsfall sollte dies höchstens einmal in der Lebensdauer eines bestimmten Tokens geschehen. Nach der Aktualisierung können Sie wahrscheinlich zukünftige Aktualisierungsanforderungen ablehnen. Danke @Frondor
John Ackerman

7

Es tut mir leid, dass ich etwas spät dran bin, aber ich hatte ähnliche Bedenken und möchte jetzt etwas dazu beitragen.

1) rdegges fügte einen ausgezeichneten Punkt hinzu, dass JWT nichts mit der "Sicherheit" zu tun hat und einfach überprüft, ob jemand die Nutzlast durcheinander gebracht hat oder nicht (Signieren); ssl hilft vor brüchen zu schützen.

2) Wenn ssl nun auch irgendwie kompromittiert wird, kann jeder Lauscher unseren Inhaber-Token (JWT) stehlen und sich als echter Benutzer ausgeben. Ein nächster Schritt besteht darin, den "Besitznachweis" von JWT beim Kunden einzuholen .

3) Mit diesem Ansatz verfügt der Moderator des JWT nun über einen bestimmten POP-Schlüssel (Proof-Of-Possession), mit dem der Empfänger kryptografisch bestätigen kann, ob die Anforderung von demselben authentischen Benutzer stammt oder nicht.

Ich habe hierzu auf den Proof of Possesion- Artikel verwiesen und bin vom Ansatz überzeugt.

Ich werde mich freuen, wenn ich etwas beitragen kann.

Prost (y)


0

Können wir nicht einfach die IP des ursprünglichen Hosts hinzufügen, der angefordert hat, dieses JWT-Token als Teil des Anspruchs zu generieren? Wenn der JWT gestohlen und von einem anderen Computer verwendet wird und der Server dieses Token überprüft, können wir überprüfen, ob die angeforderte IP-Adresse des Computers mit der im Rahmen des Anspruchs festgelegten übereinstimmt. Dies würde nicht übereinstimmen und daher kann das Token abgelehnt werden. Auch wenn der Benutzer versucht, das Token zu manipulieren, indem er seine eigene IP auf das Token setzt, wird das Token abgelehnt, wenn das Token geändert wird.


Dies ist eine mögliche Lösung, aber für Clients hinter einer Firewall ist es typisch, dass eine IP-Adresse aus einem Adresspool ausgewählt wird, und dies kann sich jederzeit ändern.
SpeedOfSpin
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.