Ist es sicher, ein JWT in LocalStorage mit Reactjs zu speichern?

147

Ich erstelle derzeit eine Einzelseitenanwendung mit reactjs. Ich habe gelesen, dass viele der Gründe für die Nichtverwendung von localStorage auf XSS-Schwachstellen zurückzuführen sind. Wäre es jetzt sicher, localStorage zu verwenden, da React allen Benutzereingaben entgeht?

Kaloyan Kosev
quelle
4
bevorzugen Sitzungsspeicher
Praneet Rohida
3
"Es wird empfohlen, keine vertraulichen Informationen im lokalen Speicher zu speichern." -OWASP "Speichern Sie sie im Speicher ohne Persistenz" -Auth0
Avejidah
Ich denke, Auth0 hat möglicherweise ihre Sichtweise geändert - da ich das obige Zitat im bereitgestellten Link nicht finden kann
DauleDK

Antworten:

141

In den meisten modernen Einzelseitenanwendungen müssen wir das Token tatsächlich irgendwo auf der Clientseite speichern (häufigster Anwendungsfall - um den Benutzer nach einer Seitenaktualisierung angemeldet zu halten).

Es stehen insgesamt 2 Optionen zur Verfügung: Webspeicher (Sitzungsspeicher, lokaler Speicher) und ein clientseitiges Cookie. Beide Optionen sind weit verbreitet, dies bedeutet jedoch nicht, dass sie sehr sicher sind.

Tom Abbott fasst die Sicherheit von JWT sessionStorage und localStorage gut zusammen :

Auf den Webspeicher (localStorage / sessionStorage) kann über JavaScript in derselben Domäne zugegriffen werden. Dies bedeutet, dass jedes auf Ihrer Site ausgeführte JavaScript Zugriff auf den Webspeicher hat und daher für Cross-Site-Scripting-Angriffe (XSS) anfällig sein kann . Kurz gesagt, XSS ist eine Art von Sicherheitsanfälligkeit, bei der ein Angreifer JavaScript einfügen kann, das auf Ihrer Seite ausgeführt wird. Grundlegende XSS-Angriffe versuchen, JavaScript über Formulareingaben einzufügen, wobei der Angreifer <script>alert('You are Hacked');</script>ein Formular erstellt, um festzustellen, ob es vom Browser ausgeführt wird und von anderen Benutzern angezeigt werden kann.

Um XSS zu verhindern, besteht die allgemeine Antwort darin, alle nicht vertrauenswürdigen Daten zu maskieren und zu verschlüsseln. Reagieren (meistens) erledigt das für Sie! Hier ist eine großartige Diskussion darüber, für wie viel XSS-Schwachstellenschutz React verantwortlich ist .

Das deckt aber nicht alle möglichen Schwachstellen ab! Eine weitere potenzielle Bedrohung ist die Verwendung von JavaScript, das auf CDNs oder außerhalb der Infrastruktur gehostet wird .

Hier ist wieder Tom:

Moderne Web-Apps enthalten JavaScript-Bibliotheken von Drittanbietern für A / B-Tests, Trichter- / Marktanalysen und Anzeigen. Wir verwenden Paketmanager wie Bower, um den Code anderer Leute in unsere Apps zu importieren.

Was ist, wenn nur eines der von Ihnen verwendeten Skripte kompromittiert wird? Schädliches JavaScript kann in die Seite eingebettet werden, und der Webspeicher ist gefährdet. Durch diese Art von XSS-Angriffen kann der Webspeicher aller Benutzer, die Ihre Website besuchen, ohne deren Wissen abgerufen werden. Dies ist wahrscheinlich der Grund, warum eine Reihe von Organisationen raten, nichts Wertvolles zu speichern oder Informationen im Webspeicher zu vertrauen. Dies umfasst Sitzungskennungen und Token.

Daher bin ich zu dem Schluss gekommen, dass Web Storage als Speichermechanismus während der Übertragung keine sicheren Standards erzwingt . Wer Web Storage liest und verwendet, muss seine Sorgfalt walten lassen, um sicherzustellen, dass die JWT immer über HTTPS und niemals über HTTP gesendet wird.

Kaloyan Kosev
quelle
10
Wenn ich Sie richtig verstehe, empfehlen Sie Cookies? Nur um sicher zugehen. Vielen Dank!
SuperLemon
7
Ja. Ich empfehle Cookies aufgrund der zusätzlichen Sicherheit, die sie bieten, und der Einfachheit des Schutzes vor CSRF mit modernen Webframeworks. Web Storage (localStorage / sessionStorage) ist anfällig für XSS, hat eine größere Angriffsfläche und kann sich auf alle Anwendungsbenutzer bei einem erfolgreichen Angriff auswirken.
Kaloyan Kosev
48
Ich denke, Sie haben diese verwechselt? Moderne Web-Frameworks verfügen über eine starke integrierte Verteidigung für XSS. Aber nicht so sehr für xsrf. Die beste Verteidigung für xsrf besteht darin, die Verwendung von Cookies vollständig zu vermeiden. Der lokale Speicher ist an eine bestimmte Domäne gebunden, was bedeutet, dass eine Angreiferdomäne nicht darauf zugreifen kann. Web-Frameworks verteidigen sich gegen xss, indem sie Benutzereingaben automatisch codieren und bereinigen. Siehe angle.io/guide/security
mikejones1477
47
Wenn "Sie empfehlen Cookies [stattdessen]", kann ich Ihnen dann empfehlen, dies irgendwo in der Antwort zu sagen? Anstatt nur in den Kommentaren?
Spechter
7
Ich bin etwas spät hier, lese gerade diese Themen und bin verwirrt über eine Sache. Viele Leute reden darüber, dass Sie mit einem Nur-http-Cookie geschützt sind, wenn Sie mit Xss komprimiert sind, aber wenn Sie xss haben Der Angreifer muss Ihnen nichts stehlen. Er kann einfach einen Beitrag von der Seite erstellen, um sich mit diesem Cookie als Sie auszugeben (auch wenn er ihn nicht stehlen kann). Vermisse ich etwas ???
Borja Alvarez
35

Ich weiß, dass dies eine alte Frage ist, aber laut @ mikejones1477 entziehen sich moderne Front-End-Bibliotheken und Frameworks dem Text und bieten Ihnen Schutz vor XSS. Der Grund , warum Cookies sind keine sichere Methode Anmeldeinformationen ist , dass Cookies CSRF nicht verhindern , wenn nicht local (auch nicht vergessen , dass Cookies von Javascript zu zugänglich ist, so XSS ist nicht das große Problem hier), diese Antwort Lebenslauf , warum .

Der Grund, warum ein Authentifizierungstoken im lokalen Speicher gespeichert und manuell zu jeder Anforderung hinzugefügt wird, um vor CSRF zu schützen, ist das Schlüsselwort: manuell. Da der Browser dieses Authentifizierungstoken nicht automatisch sendet, kann er mein authn-Token nicht senden, wenn ich evil.com besuche und es schafft, einen POST http://example.com/delete-my-account zu senden Die Anfrage wird ignoriert.

Natürlich ist httpOnly der heilige Gral, aber Sie können nicht über reagjs oder ein js-Framework zugreifen, außer Sie haben immer noch eine CSRF-Schwachstelle. Meine Empfehlung wäre localstorage oder wenn Sie Cookies verwenden möchten, stellen Sie sicher, dass Sie eine Lösung für Ihr CSRF-Problem implementieren, wie es Django tut .

Stellen Sie in Bezug auf die CDNs sicher, dass Sie keine seltsamen CDNs verwenden, z. B. CDNs wie Google oder Bootstrap Provide, die von der Community verwaltet werden und keinen Schadcode enthalten. Wenn Sie sich nicht sicher sind, können Sie diese überprüfen.

Mauricio Cortazar
quelle
2
Ich bin mir nicht sicher, warum Sie sagen würden, dass Sie bei der Verwendung von Cookies immer noch anfällig für CSRF sind. Wenn Sie ein Cookie mit den Flags HttpOnly SameSite=strictund verwenden secure, werden die in den Cookies festgelegten Informationen sicher aufbewahrt. Im Gegensatz zu XSS stellen Sie einfach sicher, dass Ihrem JavaScript keine authentifizierungsbezogenen Daten wie Token und Kennwörter bekannt sind (dh nicht im Webspeicher gespeichert werden). Wenn Sie ein schädliches Skript importieren, hat dieses Skript keinen Zugriff zu sensiblen Daten. Ja, Sie haben auch über JS keinen Zugriff auf das Token, aber das sollte wirklich kein Problem sein.
Miphe
@miphe das habe ich gesagt. Das OP fragt jedoch nach einer Möglichkeit, über Javascript darauf zuzugreifen. Hier erkläre ich nur, wie ein Token, auf das über js zugegriffen werden kann, am besten gespeichert werden kann.
Mauricio Cortazar
21

Grundsätzlich ist es in Ordnung, Ihre JWT in Ihrem localStorage zu speichern.

Und ich denke, das ist ein guter Weg. Wenn es sich um XSS handelt, XSS mit CDN, besteht auch ein potenzielles Risiko, dass Ihr Kunde sich anmeldet / weitergibt. Das Speichern von Daten im lokalen Speicher verhindert zumindest CSRF-Angriffe.

Sie müssen sich beider bewusst sein und auswählen, was Sie wollen. Beide Angriffe sind nicht alles, worauf Sie achten müssen. Denken Sie daran: Ihre gesamte App ist nur so sicher wie der letzte sichere Punkt Ihrer App.

Wieder ist das Speichern in Ordnung, sei anfällig für XSS, CSRF, ... nicht

Alex Lyalka
quelle
2
Aus diesem Grund ist es sicher, Folgendes zu tun: - Speichern Sie das JWT in einem Cookie, damit es nicht von XSS abgerufen werden kann. - Speichern Sie ein CSRF-Token in localStorage, damit es nicht von CSRF abgerufen werden kann.
Alejandro Cavazos
33
Sie sprechen einen guten Punkt an: Wenn auf Ihrer Website ein schädliches Skript ausgeführt wird, ist das Spiel trotzdem beendet. Sie können einfach Keydown-Ereignisse an Eingaben vom Typ Kennwort binden und auf diese Weise die Authentifizierungsinformationen Ihres Benutzers stehlen (was viel, viel schlimmer ist als das Stehlen eines JWT-Authentifizierungstokens). Das Speichern von JWTs in localStorage trägt wenig dazu bei, den ohnehin immensen möglichen Schaden durch XSS zu erhöhen.
Carl Leth
8

Es ist nicht sicher, wenn Sie CDNs verwenden:

Schädliches JavaScript kann in die Seite eingebettet werden, und der Webspeicher ist gefährdet. Durch diese Art von XSS-Angriffen kann der Webspeicher aller Benutzer, die Ihre Website besuchen, ohne deren Wissen abgerufen werden. Dies ist wahrscheinlich der Grund, warum eine Reihe von Organisationen raten, nichts Wertvolles zu speichern oder Informationen im Webspeicher zu vertrauen. Dies umfasst Sitzungskennungen und Token.

über Sturmweg

Jedes Skript, das Sie von außen benötigen, kann möglicherweise kompromittiert werden und JWTS aus dem Speicher Ihres Clients abrufen und persönliche Daten an den Server des Angreifers zurücksenden.

Stephen L.
quelle
6
Wenn ich nicht vorhabe, CDns zu verwenden, ist es dann sicher?
1
Der Autor des Artikels hat nie zwischen XSS auf Websites unterschieden, die über ein CDN oder direkt von einem zentralen Server aus bedient werden. Würde Ihre Erklärung hier nicht auch allgemein gelten, nicht nur für CDNs?
Vlad
4

Localstorage ist so konzipiert, dass es über Javascript zugänglich ist, sodass es keinen XSS-Schutz bietet. Wie in anderen Antworten erwähnt, gibt es eine Reihe von Möglichkeiten, einen XSS-Angriff durchzuführen, vor denen localstorage standardmäßig nicht geschützt ist.

Cookies verfügen jedoch über Sicherheitsflags, die vor XSS- und CSRF-Angriffen schützen. Das HttpOnly-Flag verhindert, dass clientseitiges Javascript auf das Cookie zugreift. Das Secure-Flag ermöglicht dem Browser nur, das Cookie über ssl zu übertragen, und das SameSite-Flag stellt sicher, dass das Cookie nur an den Ursprung gesendet wird. Obwohl ich gerade überprüft habe und SameSite derzeit nur in Opera und Chrome unterstützt wird, ist es zum Schutz vor CSRF besser, andere Strategien zu verwenden. Beispiel: Senden eines verschlüsselten Tokens in einem anderen Cookie mit einigen öffentlichen Benutzerdaten.

Cookies sind daher eine sicherere Wahl zum Speichern von Authentifizierungsdaten.

Ivan
quelle
kann nicht bekommen: wie kann HttpOnly Sie vor CSRF schützen?
Alex Lyalka
@AlexLyalka Wollte nicht sagen, dass HttpOnly CSRF verhindert, anstatt dass alle Cookie-Flags zusammen vor XSS und CSRF schützen können. SameSite bietet einen gewissen Schutz und verhindert, dass die Cookies an eine andere Website als den Ursprung gesendet werden. Obwohl ich gerade überprüft habe und die Unterstützung für diese Flagge sehr gering ist. Es ist auch möglich, CSRF mit einem separaten verschlüsselten Token mit einer Benutzeridentifikation zu vermeiden, das auf dem Server überprüft wird.
Ivan
1
Wenn jemand Code in Ihrem Web ausführen kann, kann er dann nicht einfach im Namen Ihres Benutzers einen Beitrag in Ihrem Web verfassen? Ok, er kann nicht nur Ihre http-Cookies bekommen, aber er kann mit diesen Cookies Anrufe tätigen, also kann ich den Punkt immer noch nicht sehen
Borja Alvarez
2
@ BorjaAlverez Es gibt einen großen Unterschied. Ja, über XSS könnte jemand Anfragen im Namen des angemeldeten Benutzers stellen, aber die Gefährdung eines Tokens ist schlimmer. Beispiel: Das Token bietet möglicherweise Zugriff auf APIs, die von der Clientanwendung nicht verwendet werden. Das Token kann andere Informationen über den Benutzer enthalten (E-Mail-Adresse, Profil und Zuschüsse). Das Token kann für Wiederholungsangriffe gegen Ihre Anwendung verwendet werden. Das Token kann als id_token_hintan einen OIDC-Authentifizierungsserver übergeben werden. Das Token enthält Informationen des Angreifers über die Chiffre, mit der es signiert wurde. usw.
Avejidah
3

Eine Möglichkeit, dies zu betrachten, besteht darin, das Risiko oder den Schaden zu berücksichtigen.

Erstellen Sie eine App ohne Benutzer, POC / MVP? Sind Sie ein Startup, das Ihre App schnell auf den Markt bringen und testen muss? Wenn ja, würde ich wahrscheinlich nur die einfachste Lösung implementieren und mich weiterhin darauf konzentrieren, eine marktgerechte Lösung zu finden. Verwenden Sie localStorage, da es häufig einfacher zu implementieren ist.

Erstellen Sie eine Version 2 einer App mit vielen täglich aktiven Benutzern oder eine App, von der Personen / Unternehmen stark abhängig sind? Würde es wenig oder gar keinen Raum für Erholung bedeuten, gehackt zu werden? In diesem Fall würde ich mich eingehend mit Ihren Abhängigkeiten befassen und in Betracht ziehen, Token-Informationen in einem Nur-http-Cookie zu speichern.

Die Verwendung von localStorage und Cookie- / Sitzungsspeicher hat ihre eigenen Vor- und Nachteile.

Wie in der ersten Antwort angegeben: Wenn Ihre Anwendung eine XSS-Sicherheitsanfälligkeit aufweist, schützt keiner Ihrer Benutzer. Da die meisten modernen Anwendungen ein Dutzend oder mehr verschiedene Abhängigkeiten aufweisen, wird es immer schwieriger, sicherzustellen, dass eine der Abhängigkeiten Ihrer Anwendung nicht XSS-anfällig ist.

Wenn Ihre Anwendung eine XSS-Sicherheitsanfälligkeit aufweist und ein Hacker diese ausnutzen konnte, kann der Hacker Aktionen für Ihren Benutzer ausführen. Der Hacker kann GET / POST-Anforderungen ausführen, indem er ein Token aus localStorage abruft, oder POST-Anforderungen ausführen, wenn das Token in einem Nur-http-Cookie gespeichert ist.

Der einzige Nachteil beim Speichern Ihres Tokens im lokalen Speicher ist, dass der Hacker Ihr Token lesen kann.

HenokG
quelle
1

Ist weder localStorage noch httpOnly-Cookie akzeptabel? In Bezug auf eine kompromittierte Bibliothek von Drittanbietern ist die einzige mir bekannte Lösung, die den Diebstahl sensibler Informationen reduziert / verhindert, die Durchsetzung der Subresource-Integrität .

Subresource Integrity (SRI) ist eine Sicherheitsfunktion, mit der Browser überprüfen können, ob die von ihnen abgerufenen Ressourcen (z. B. von einem CDN) ohne unerwartete Manipulation bereitgestellt werden. Es ermöglicht Ihnen, einen kryptografischen Hash bereitzustellen, mit dem eine abgerufene Ressource übereinstimmen muss.

Solange die gefährdete Bibliothek eines Drittanbieters auf Ihrer Website aktiv ist, kann ein Keylogger Informationen wie Benutzername, Passwort und alles, was Sie sonst noch in die Website eingeben, sammeln.

Ein httpOnly-Cookie verhindert den Zugriff von einem anderen Computer, verhindert jedoch nicht, dass der Hacker den Computer des Benutzers manipuliert.

LEISE
quelle
-10

Es ist sicher, Ihr Token in localStorage zu speichern, solange Sie es verschlüsseln. Unten finden Sie einen komprimierten Code-Ausschnitt, der eine von vielen Möglichkeiten zeigt, wie Sie dies tun können.

    import SimpleCrypto from 'simple-crypto-js';

    const saveToken = (token = '') => {
          const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
          const encryptedToken = encryptInit.encrypt(token);

          localStorage.setItem('token', encryptedToken);
     }

Bevor Sie Ihr Token verwenden, entschlüsseln Sie es mit PRIVATE_KEY_STORED_IN_ENV_FILE

Kidali Kevin
quelle
@HassanAlthaf Sie verpassen den Punkt hier, es wird nie eine 100% sichere Proof-App geben. Es ist nur so, dass Sie die Angriffsfläche reduzieren und zumindest die env-Datei nicht direkt auf github veröffentlicht wird. Außerdem wird der gebündelte Code verschleiert und entstellt, was es den Angreifern erschwert, sie zu finden.
Kidali Kevin
Der private Schlüssel darf nicht offengelegt werden. Sie würden die gesamte API gefährden.
Hassan Althaf
Aus meiner Erfahrung Wenn Sie die Dinge intelligent und korrekt gemacht haben, wird Ihr privater Schlüssel in Ihrem Produktions-Build nicht angezeigt. Wenn ja, Screenshot, um dies oder sogar eine URL zu unterstützen.
Kidali Kevin