Wenn Sie JWT dekodieren können, wie sind sie sicher?

302

Wie ist das sicher, wenn ich eine JWT bekomme und die Nutzlast entschlüsseln kann? Könnte ich nicht einfach das Token aus dem Header holen, die Benutzerinformationen in der Nutzlast dekodieren und ändern und sie mit demselben korrekt codierten Geheimnis zurücksenden?

Ich weiß, dass sie sicher sein müssen, aber ich möchte die Technologien wirklich verstehen. Was vermisse ich?

PixMach
quelle
2
md5('original messaged' + secret) != md5('changed message' + secret)Wenn also jemand die Nachricht ändert, können Sie sie erkennen
Pithikos
Im Idealfall hat md5 jedoch Kollisionen. @Pithikos
Yash Kumar Verma
@YashKumarVerma ja, es ist nur um das Wesentliche zu demonstrieren, da jeder md5 kennt.
Pithikos
1
@ user1955934 es ist base64-codiert, NICHT verschlüsselt. Sie können es einfach mit jedem base64-Decoder dekodieren.
Pithikos
1
Muss der Client also sowohl den Hash als auch das JWT-Token senden? und später auf der Serverseite werden sie versuchen, das JWT-Token mit Secret zu hashen und mit dem Hash zu vergleichen?
user1955934

Antworten:

387

JWTs können entweder signiert, verschlüsselt oder beides sein. Wenn ein Token signiert, aber nicht verschlüsselt ist, kann jeder seinen Inhalt lesen. Wenn Sie den privaten Schlüssel jedoch nicht kennen, können Sie ihn nicht ändern. Andernfalls wird der Empfänger feststellen, dass die Signatur nicht mehr übereinstimmt.

Antwort auf Ihren Kommentar: Ich bin mir nicht sicher, ob ich Ihren Kommentar richtig verstehe. Nur um sicher zu gehen: Kennen und verstehen Sie digitale Signaturen? Ich werde nur kurz eine Variante erklären (HMAC, die symmetrisch ist, aber es gibt viele andere).

Nehmen wir an, Alice möchte einen JWT an Bob senden. Beide kennen ein gemeinsames Geheimnis. Mallory kennt dieses Geheimnis nicht, will sich aber einmischen und die JWT ändern. Um dies zu verhindern, berechnet Alice dies Hash(payload + secret)und hängt es als Signatur an.

Beim Empfang der Nachricht kann Bob auch berechnen Hash(payload + secret), ob die Signatur übereinstimmt. Wenn Mallory jedoch etwas am Inhalt ändert, kann sie die passende Signatur nicht berechnen (was wäre Hash(newContent + secret)). Sie kennt das Geheimnis nicht und kann es nicht herausfinden. Das heißt, wenn sie etwas ändert, stimmt die Signatur nicht mehr überein und Bob akzeptiert die JWT einfach nicht mehr.

Nehmen wir an, ich sende einer anderen Person die Nachricht {"id":1}und unterschreibe sie mit Hash(content + secret). (+ ist hier nur Verkettung). Ich verwende die SHA256-Hash-Funktion und die Signatur, die ich erhalte, lautet : 330e7b0775561c6e95797d4dd306a150046e239986f0a1373230fda0235bda8c. Jetzt sind Sie dran: Spielen Sie die Rolle von Mallory und versuchen Sie, die Nachricht zu unterschreiben {"id":2}. Sie können nicht, weil Sie nicht wissen, welches Geheimnis ich verwendet habe. Wenn der Empfänger das Geheimnis kennt, kann er die Signatur einer Nachricht berechnen und prüfen, ob sie korrekt ist.

Misch
quelle
8
Also wird die Signatur geändert, wenn die Nutzlast geändert wird? Ich hatte den Eindruck, dass das Token das Format [Header] hat. [Nutzlast]. [Signatur] Wird die Signatur durch Kombination von Nutzlast und Geheimnis berechnet? Wenn dies der Fall wäre, wäre eine Nutzlast mit einer anderen ID für dieses Geheimnis nicht dieselbe? Wenn die Daten {id: 1} wären und damit der Signaturteil des Tokens mit dem Geheimnis berechnet wird, würde dies nicht bedeuten, dass {id: 2} für Benutzer 2 gültig wäre und sich daher Benutzer 1 ändern könnte ID zu 2 und das Token wäre das gleiche?
PixMach
7
Ich habe Ihnen ein Beispiel gegeben, um die Dinge noch klarer zu machen, aber ich werde Ihnen nicht das gesamte Konzept der digitalen Signaturen und HMACs erklären. Bitte lesen Sie über diese Dinge nach, es gibt viel Material, das es erklärt.
Misch
11
Oh jetzt verstehe ich. Ich weiß nicht, warum mir die Idee gefehlt hat, dass der geheime Hash nicht korrekt ist, wenn Sie die Nutzlast geändert haben, da der geheime Hash neu berechnet werden müsste. Aus irgendeinem Grund dachte ich immer noch, dass es unabhängig war. Das letzte bisschen hat es für mich wirklich nach Hause gebohrt. Danke, dass du mich durch die Sache geführt hast.
PixMach
30
Ich habe eine verwandte Frage. Was hindert jemanden daran, sich mit dem kopierten JWT als Alice auszugeben?
Morrowless
25
Wenn jemand die JWT hat, kann er sich als Alice ausgeben. Sie müssen also vorsichtig sein, wie Sie es speichern und senden. Sie sollten auch einen Ablauf dafür in der Nutzlast festlegen. Auf diese Weise hat jemand, der das JWT stiehlt, einen begrenzten Zeitrahmen, um es zu verwenden. Werfen
Geraint Anderson
134

Sie können zu gehen jwt.io, Ihren Token einfügen und den Inhalt lesen. Dies ist für viele Menschen anfangs ein Witz.

Die kurze Antwort lautet, dass sich JWT nicht mit Verschlüsselung befasst. Es geht um die Validierung. Das heißt, es kann immer die Antwort für "Haben Sie den Inhalt dieses Tokens manipuliert" bekommen? Dies bedeutet, dass die Manipulation des JWT-Tokens durch den Benutzer zwecklos ist, da der Server das Token kennt und ignoriert. Der Server fügt eine Signatur basierend auf der Nutzlast hinzu, wenn ein Token an den Client ausgegeben wird. Später werden die Nutzdaten und die übereinstimmende Signatur überprüft.

Die logische Frage ist, was die Motivation ist, sich nicht mit verschlüsselten Inhalten zu befassen.

  1. Der einfachste Grund ist, dass davon ausgegangen wird, dass dies größtenteils ein gelöstes Problem ist. Wenn Sie mit einem Client wie dem Webbrowser arbeiten, können Sie die JWT-Token in einem Cookie speichern, das secure(nicht über HTTP, nur über HTTPS übertragen) und httpOnly(kann nicht von Javascript gelesen werden) und mit dem Server über kommuniziert ein verschlüsselter Kanal (HTTPS). Sobald Sie wissen, dass Sie einen sicheren Kanal zwischen Server und Client haben, können Sie JWT oder was auch immer Sie möchten sicher austauschen.

  2. Das hält die Sache einfach. Eine einfache Implementierung erleichtert die Übernahme, lässt aber auch jede Schicht das tun, was sie am besten kann (lassen Sie HTTPS die Verschlüsselung übernehmen).

  3. JWT ist nicht zum Speichern sensibler Daten gedacht. Sobald der Server das JWT-Token empfangen und validiert hat, kann er die Benutzer-ID in seiner eigenen Datenbank nach zusätzlichen Informationen für diesen Benutzer durchsuchen (z. B. Berechtigungen, Postanschrift usw.). Dies hält JWT klein und vermeidet versehentliche Informationslecks, da jeder weiß, dass vertrauliche Daten nicht in JWT gespeichert werden.

Es unterscheidet sich nicht allzu sehr von der Funktionsweise von Cookies. Cookies enthalten häufig unverschlüsselte Nutzdaten. Wenn Sie HTTPS verwenden, ist alles gut. Wenn dies nicht der Fall ist, ist es ratsam, vertrauliche Cookies selbst zu verschlüsseln. Wenn Sie dies nicht tun, ist ein Man-in-the-Middle-Angriff möglich. Ein Proxyserver oder ISP liest die Cookies und spielt sie später erneut ab, wenn Sie sich als Sie ausgeben. Aus ähnlichen Gründen sollte JWT immer über eine sichere Schicht wie HTTPS ausgetauscht werden.

Aleemb
quelle
4
Was dagegen! JWT sollte immer über eine sichere Schicht wie HTTPS
Codemirror
Aber wenn JWT nur über HTTPS sicher ist, warum nicht einfach die Nutzdaten senden? POST -> Benutzername, Passwort. Es ist immer noch verschlüsselt, oder?
GeekPeek
@GeekPeek dafür sollten Sie sich über die JWT-Grundlagen informieren, aber Session Auth, wie Sie es erwähnen, ist oft alles, was Sie brauchen. JWT bietet einige andere Vorteile, macht aber einige Kompromisse webskeleton.com/webdev/2019/10/22/…
aleemb
17

Der Inhalt eines JSON-Web-Tokens (JWT) ist nicht von Natur aus sicher, es gibt jedoch eine integrierte Funktion zum Überprüfen der Token-Authentizität. Ein JWT besteht aus drei durch Punkte getrennten Hashes. Der dritte ist die Unterschrift. In einem öffentlichen / privaten Schlüsselsystem signiert der Aussteller die Tokensignatur mit einem privaten Schlüssel, der nur durch seinen entsprechenden öffentlichen Schlüssel überprüft werden kann.

Es ist wichtig, die Unterscheidung zwischen Emittent und Prüfer zu verstehen. Der Empfänger des Tokens ist für die Überprüfung verantwortlich.

Es gibt zwei wichtige Schritte, um JWT sicher in einer Webanwendung zu verwenden: 1) Senden Sie sie über einen verschlüsselten Kanal und 2) Überprüfen Sie die Signatur sofort nach dem Empfang. Die asymmetrische Natur der Kryptographie mit öffentlichen Schlüsseln ermöglicht die Überprüfung der JWT-Signatur. Ein öffentlicher Schlüssel überprüft, ob ein JWT mit seinem passenden privaten Schlüssel signiert wurde. Keine andere Tastenkombination kann diese Überprüfung durchführen, wodurch Identitätswechselversuche verhindert werden. Befolgen Sie diese beiden Schritte und wir können mit mathematischer Sicherheit die Echtheit eines JWT garantieren.

Lesen Sie weiter: Wie überprüft ein öffentlicher Schlüssel eine Signatur?

ThisClark
quelle
2

Lassen Sie uns von Anfang an davon sprechen:

JWT ist ein sehr moderner, einfacher und sicherer Ansatz, der sich auch auf Json Web Tokens erstreckt. Json Web Tokens sind eine zustandslose Lösung für die Authentifizierung. Es ist also nicht erforderlich, einen Sitzungsstatus auf dem Server zu speichern, was natürlich perfekt für erholsame APIs ist. Restful APIs sollten immer zustandslos sein. Die am häufigsten verwendete Alternative zur Authentifizierung mit JWTs besteht darin, den Anmeldestatus des Benutzers nur mithilfe von Sitzungen auf dem Server zu speichern. Aber dann folgt natürlich nicht das Prinzip, dass erholsame APIs zustandslos sein sollten, und deshalb wurden Lösungen wie JWT populär und effektiv.

Lassen Sie uns nun wissen, wie die Authentifizierung mit Json-Web-Tokens tatsächlich funktioniert. Vorausgesetzt, wir haben bereits einen registrierten Benutzer in unserer Datenbank. Der Client des Benutzers stellt zunächst eine Post-Anfrage mit dem Benutzernamen und dem Kennwort. Die Anwendung prüft dann, ob der Benutzer vorhanden ist. Wenn das Kennwort korrekt ist, generiert die Anwendung ein eindeutiges Json-Web-Token nur für diesen Benutzer.

Das Token wird mithilfe einer geheimen Zeichenfolge erstellt , die auf einem Server gespeichert ist . Als nächstes sendet der Server diese JWT an den Client zurück, der sie entweder in einem Cookie oder in einem lokalen Speicher speichert. Geben Sie hier die Bildbeschreibung ein

Auf diese Weise wird der Benutzer authentifiziert und im Grunde genommen in unserer Anwendung angemeldet, ohne dass ein Status auf dem Server verbleibt.

Der Server weiß also tatsächlich nicht, welcher Benutzer tatsächlich angemeldet ist, aber natürlich weiß der Benutzer, dass er angemeldet ist, weil er über ein gültiges Json-Web-Token verfügt, das ein bisschen wie ein Pass für den Zugriff auf geschützte Teile der Anwendung ist.

Also noch einmal, nur um sicherzugehen, dass Sie auf die Idee gekommen sind. Ein Benutzer wird angemeldet, sobald er sein eindeutiges gültiges Json-Web-Token zurückerhält, das nirgendwo auf dem Server gespeichert ist. Und so ist dieser Prozess völlig zustandslos.

Jedes Mal, wenn ein Benutzer auf eine geschützte Route zugreifen möchte, wie beispielsweise seine Benutzerprofildaten. Er sendet sein Json-Web-Token zusammen mit einer Anfrage. Es ist also ein bisschen so, als würde er seinen Reisepass vorzeigen, um Zugang zu dieser Route zu erhalten.

Sobald die Anfrage den Server erreicht, überprüft unsere App, ob das Json-Web-Token tatsächlich gültig ist und ob der Benutzer wirklich der ist, von dem er sagt, dass er er ist. Nun, dann werden die angeforderten Daten an den Client gesendet, und wenn nicht, wird dies der Fall sein ein Fehler sein, der dem Benutzer mitteilt, dass er nicht auf diese Ressource zugreifen darf. Geben Sie hier die Bildbeschreibung ein

All diese Kommunikation muss über https erfolgen, also sicheres verschlüsseltes HTTP, um zu verhindern, dass jeder Zugriff auf Passwörter oder Json-Web-Token erhält. Nur dann haben wir ein wirklich sicheres System.

Geben Sie hier die Bildbeschreibung ein

Ein Json-Web-Token sieht also wie der linke Teil dieses Screenshots aus, der aus dem JWT-Debugger bei jwt.ioSo stammt. Es handelt sich also im Wesentlichen um eine Codierungszeichenfolge, die aus drei Teilen besteht. Der Header, die Nutzdaten und die Signatur Jetzt sind die Kopfzeilen nur noch einige Metadaten über das Token selbst und die Nutzdaten sind die Daten, die wir in das Token codieren können, alle Daten, die wir wirklich wollen. Je mehr Daten wir hier codieren möchten, desto größer ist die JWT. Wie auch immer, diese beiden Teile sind nur einfacher Text, der verschlüsselt, aber nicht verschlüsselt wird.

Damit jeder sie entschlüsseln und lesen kann , können wir hier keine sensiblen Daten speichern. Aber das ist überhaupt kein Problem, denn im dritten Teil, also in der Signatur, werden die Dinge wirklich interessant. Die Signatur wird anhand des Headers, der Nutzdaten und des auf dem Server gespeicherten Geheimnisses erstellt.

Dieser gesamte Vorgang wird dann als Signieren des Json-Web-Tokens bezeichnet . Der Signaturalgorithmus verwendet den Header, die Nutzdaten und das Geheimnis, um eine eindeutige Signatur zu erstellen. Nur diese Daten und das Geheimnis können diese Signatur erstellen. Diese Signatur bildet dann zusammen mit dem Header und der Nutzlast die JWT, die dann an den Client gesendet wird. Geben Sie hier die Bildbeschreibung ein

Sobald der Server eine JWT erhält, um Zugriff auf eine geschützte Route zu gewähren, muss er diese überprüfen, um festzustellen, ob der Benutzer wirklich der ist, für den er sich ausgibt. Mit anderen Worten, es wird überprüft, ob niemand den Header und die Nutzdaten des Tokens geändert hat. Dieser Überprüfungsschritt überprüft also erneut, ob kein Dritter tatsächlich den Header oder die Nutzdaten des Json-Web-Tokens geändert hat.

Wie funktioniert diese Überprüfung tatsächlich? Nun, es ist eigentlich ganz einfach. Sobald die JWT empfangen wurde, nimmt die Überprüfung ihren Header und ihre Nutzdaten und erstellt zusammen mit dem Geheimnis, das noch auf dem Server gespeichert ist, im Grunde eine Testsignatur.

Aber die ursprüngliche Signatur, die beim ersten Erstellen des JWT generiert wurde, befindet sich immer noch im Token, oder? Und das ist der Schlüssel zu dieser Überprüfung. Denn jetzt müssen wir nur noch die Testsignatur mit der Originalsignatur vergleichen. Und wenn die Testsignatur mit der ursprünglichen Signatur identisch ist, bedeutet dies, dass die Nutzlast und der Header nicht geändert wurden. Geben Sie hier die Bildbeschreibung ein

Denn wenn sie geändert worden wären, müsste die Testsignatur anders sein. Daher können wir in diesem Fall, in dem die Daten nicht geändert wurden, den Benutzer authentifizieren. Und wenn die beiden Signaturen tatsächlich unterschiedlich sind, bedeutet dies natürlich, dass jemand die Daten manipuliert hat. Normalerweise durch den Versuch, die Nutzlast zu ändern. Aber dieser Dritte, der die Nutzlast manipuliert, hat natürlich keinen Zugriff auf das Geheimnis, so dass er das JWT nicht unterzeichnen kann. Die ursprüngliche Signatur entspricht also niemals den manipulierten Daten. Daher schlägt die Überprüfung in diesem Fall immer fehl. Und das ist der Schlüssel, damit dieses ganze System funktioniert. Es ist die Magie, die JWT so einfach, aber auch extrem mächtig macht.

Herr
quelle
1

Nur der privateKey von JWT, der sich auf Ihrem Server befindet, entschlüsselt den verschlüsselten JWT. Diejenigen, die den privateKey kennen, können den verschlüsselten JWT entschlüsseln.

Verstecken Sie den privaten Schlüssel an einem sicheren Ort auf Ihrem Server und teilen Sie niemandem den privaten Schlüssel mit.

sdfdsf sdf
quelle
1
JWTs werden nicht immer verschlüsselt. Sie können signiert, verschlüsselt, signiert und dann verschlüsselt oder verschlüsselt und dann signiert werden.
Csauve
0

Für Leute, die sich wie ich keine teuren Datenbankabfragen leisten können, besteht eine Möglichkeit, vertrauliche Daten (Benutzerrechte usw.) zu behalten, darin, diese Daten beim Generieren des JWT zu verschlüsseln und an das JWT-Token anzuhängen. (Bewahren Sie den Verschlüsselungsschlüssel im Backend auf.)

Wenn Sie die vertraulichen Informationen lesen möchten, können Sie das JWT-Token an das Backend senden, es entschlüsseln und die Informationen zurückerhalten. Auf diese Weise müssen Sie keine DB-Suchvorgänge durchführen oder die vertraulichen Informationen über das JWT-Token nackt im Frontend haben

Nirojan Selvanathan
quelle
-1

Ich würde vorschlagen, einen Blick in JWE mit speziellen Algorithmen zu werfen, die in jwt.io nicht zum Entschlüsseln vorhanden sind

Referenzlink: https://www.npmjs.com/package/node-webtokens

jwt.generate('PBES2-HS512+A256KW', 'A256GCM', payload, pwd, (error, token) => {
  jwt.parse(token).verify(pwd, (error, parsedToken) => {
    // other statements
  });
});

Diese Antwort ist möglicherweise zu spät oder Sie haben den Weg bereits herausgefunden, aber ich hatte trotzdem das Gefühl, dass sie auch für Sie und andere hilfreich sein würde.

Ein einfaches Beispiel, das ich erstellt habe: https://github.com/hansiemithun/jwe-example

Mithun Shreevatsa
quelle