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?
security
jwt
express-jwt
PixMach
quelle
quelle
md5('original messaged' + secret) != md5('changed message' + secret)
Wenn also jemand die Nachricht ändert, können Sie sie erkennenAntworten:
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äreHash(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 mitHash(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.quelle
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.
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) undhttpOnly
(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.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).
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.
quelle
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?
quelle
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.
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.
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.
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.
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.
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.
quelle
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.
quelle
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
quelle
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
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
quelle