Est-il sûr de stocker un jwt dans localStorage avec reactjs?

147

Je construis actuellement une application d'une seule page en utilisant reactjs. J'ai lu que la plupart des raisons de ne pas utiliser localStorage sont dues aux vulnérabilités XSS. Puisque React échappe à toutes les entrées de l'utilisateur, serait-il maintenant sûr d'utiliser localStorage?

Kaloyan Kosev
la source
4
prefer Session Storage
Praneet Rohida
3
"Il est recommandé de ne pas stocker d'informations sensibles dans le stockage local." -OWASP "les stocker en mémoire sans aucune persistance" -Auth0
avejidah
Je pense qu'Auth0 a peut-être changé de point de vue à ce sujet - car je ne trouve pas la citation ci-dessus dans le lien fourni
DauleDK

Réponses:

141

Dans la plupart des applications modernes à une seule page, nous devons en effet stocker le jeton quelque part du côté client (cas d'utilisation le plus courant - pour garder l'utilisateur connecté après une actualisation de la page).

Il y a un total de 2 options disponibles: Stockage Web (stockage de session, stockage local) et un cookie côté client. Les deux options sont largement utilisées, mais cela ne signifie pas qu'elles sont très sécurisées.

Tom Abbott résume bien la sécurité JWT sessionStorage et localStorage :

Le stockage Web (localStorage / sessionStorage) est accessible via JavaScript sur le même domaine. Cela signifie que tout JavaScript s'exécutant sur votre site aura accès au stockage Web et, de ce fait, peut être vulnérable aux attaques de scripts intersites (XSS) . XSS, en un mot, est un type de vulnérabilité dans lequel un attaquant peut injecter du JavaScript qui s'exécutera sur votre page. Les attaques XSS de base tentent d'injecter du JavaScript via des entrées de formulaire, où l'attaquant le met <script>alert('You are Hacked');</script>dans un formulaire pour voir s'il est exécuté par le navigateur et peut être consulté par d'autres utilisateurs.

Pour empêcher XSS, la réponse courante consiste à échapper et à encoder toutes les données non approuvées. React le fait (principalement) pour vous! Voici une excellente discussion sur le niveau de protection contre les vulnérabilités XSS dont React est responsable .

Mais cela ne couvre pas toutes les vulnérabilités possibles! Une autre menace potentielle est l'utilisation de JavaScript hébergé sur des CDN ou une infrastructure externe .

Voici à nouveau Tom:

Les applications Web modernes incluent des bibliothèques JavaScript tierces pour les tests A / B, les analyses d'entonnoir / marché et les publicités. Nous utilisons des gestionnaires de packages comme Bower pour importer le code d'autres personnes dans nos applications.

Et si un seul des scripts que vous utilisez est compromis? Un code JavaScript malveillant peut être intégré à la page et le stockage Web est compromis. Ces types d'attaques XSS peuvent obtenir le stockage Web de tout le monde qui visite votre site, à leur insu. C'est probablement pourquoi de nombreuses organisations conseillent de ne pas stocker quoi que ce soit de valeur ou de ne faire confiance à aucune information dans le stockage Web. Cela inclut les identifiants de session et les jetons.

Par conséquent, ma conclusion est qu'en tant que mécanisme de stockage, le stockage Web n'applique aucune norme de sécurité pendant le transfert . Quiconque lit le stockage Web et l'utilise doit faire preuve de diligence raisonnable pour s'assurer qu'il envoie toujours le JWT via HTTPS et jamais via HTTP.

Kaloyan Kosev
la source
10
Donc, si je vous comprends bien, vous recommandez les cookies? Juste pour en être certain. Merci!
SuperLemon
7
Oui. Je recommande les cookies en raison de la sécurité supplémentaire qu'ils offrent et de la simplicité de protection contre la CSRF avec des cadres Web modernes. Le stockage Web (localStorage / sessionStorage) est vulnérable à XSS, a une plus grande surface d'attaque et peut avoir un impact sur tous les utilisateurs de l'application en cas d'attaque réussie.
Kaloyan Kosev le
48
Je pense que vous les avez mélangés? Les frameworks Web modernes ont de solides défenses intégrées pour XSS. Mais pas tant pour xsrf. La meilleure défense pour xsrf est d'éviter complètement d'utiliser des cookies. Le stockage local est mis en sandbox sur un domaine spécifique, ce qui signifie qu'un domaine attaquant ne peut pas y accéder. Les frameworks Web se défendent contre xss en encodant et en désinfectant automatiquement les entrées utilisateur. Voir angular.io/guide/security
mikejones1477
47
Si "vous recommandez des cookies [à la place]", puis-je vous recommander de dire cela quelque part dans la réponse? Plutôt que juste dans les commentaires?
spechter
7
Je suis ici un peu en retard, je viens de lire ces sujets maintenant et je suis confus sur une chose, beaucoup de gens disent que vous êtes protégé par un cookie http uniquement si vous êtes compromis avec Xss, mais, si vous avez xss l'attaquant n'a pas besoin de vous voler quoi que ce soit, il peut simplement créer un message à partir de la page pour vous faire passer pour vous en utilisant ce cookie (même s'il ne peut pas le voler). Est-ce que je manque quelque chose ???
Borja Alvarez le
36

Je sais que c'est une vieille question, mais selon ce que @ mikejones1477 a dit, les bibliothèques et les frameworks frontaux modernes échappent au texte et vous protègent contre XSS. La raison pour laquelle les cookies ne sont pas une méthode sécurisée utilisant des informations d'identification est que les cookies n'empêchent pas CSRF lorsque localStorage le fait (rappelez-vous également que les cookies sont également accessibles par javascript, donc XSS n'est pas le gros problème ici), cette réponse résume pourquoi .

La raison pour laquelle stocker un jeton d'authentification dans le stockage local et l'ajouter manuellement à chaque demande protège contre CSRF est ce mot clé: manuel. Étant donné que le navigateur n'envoie pas automatiquement ce jeton d'authentification, si je visite evil.com et qu'il parvient à envoyer un POST http://example.com/delete-my-account , il ne pourra pas envoyer mon jeton d'authentification, donc la demande est ignorée.

Bien sûr, httpOnly est le Saint Graal, mais vous ne pouvez pas accéder à partir de reactjs ou de tout autre framework js à côté de vous avez toujours une vulnérabilité CSRF. Ma recommandation serait localstorage ou si vous souhaitez utiliser des cookies, assurez-vous d'implémenter une solution à votre problème CSRF comme le fait django .

En ce qui concerne les CDN, assurez-vous que vous n'utilisez pas de CDN étranges, par exemple CDN comme google ou bootstrap, sont maintenus par la communauté et ne contiennent pas de code malveillant, si vous n'êtes pas sûr, vous êtes libre de les examiner.

Mauricio Cortazar
la source
2
Je ne sais pas pourquoi vous diriez que vous êtes toujours vulnérable au CSRF lorsque vous utilisez des cookies. L'utilisation d'un cookie avec les indicateurs HttpOnly SameSite=strictet secure, gardera en sécurité les informations que vous avez définies dans les cookies. Ensuite, contre XSS, vous vous assurez simplement que votre JavaScript n'est pas au courant des données liées à l'authentification, comme les jetons et les mots de passe (ce qui signifie, ne les stockez pas dans le stockage Web) - si vous importez un script malveillant, ce script n'aura pas accès aux données sensibles. Oui, vous n'aurez pas non plus accès au jeton via JS, mais cela ne devrait vraiment pas être un problème.
miphe
@miphe c'est ce que j'ai dit. Mais l'OP demande un moyen d'accéder à partir de javascript. Ici, j'explique simplement quelle est la meilleure façon de stocker un jeton accessible depuis js.
Mauricio Cortazar du
21

Fondamentalement, vous pouvez stocker votre JWT dans votre stockage local.

Et je pense que c'est un bon moyen. Si nous parlons de XSS, XSS utilisant CDN, c'est également un risque potentiel d'obtenir également le login / pass de votre client. Le stockage des données dans le stockage local empêchera au moins les attaques CSRF.

Vous devez être conscient des deux et choisir ce que vous voulez. Les deux attaques ne sont pas tout ce dont vous avez besoin d'être conscient, rappelez-vous simplement: VOTRE APPLICATION ENTIÈRE EST UNIQUEMENT AUSSI SÉCURISÉE QUE LE POINT LE MOINS SÉCURISÉ DE VOTRE APP.

Encore une fois, le stockage est OK, soyez vulnérable à XSS, CSRF, ... n'est pas

Alex Lyalka
la source
2
C'est pourquoi il est sûr de faire ce qui suit: - Stockez le JWT dans un cookie afin qu'il ne puisse pas être récupéré à partir de XSS - Stockez un jeton CSRF dans localStorage afin qu'il ne puisse pas être récupéré depuis CSRF
Alejandro Cavazos
33
Vous soulevez un bon point: si votre site exécute un script malveillant, la partie est terminée de toute façon. Ils peuvent simplement lier les événements keydown à des entrées de type mot de passe et voler les informations d'authentification de votre utilisateur de cette façon (ce qui est bien pire que de voler un jeton d'authentification JWT). Le stockage des JWT dans localStorage ne fait pas grand-chose pour augmenter les dégâts déjà immenses possibles de XSS.
Carl Leth
8

Ce n'est pas sûr si vous utilisez des CDN:

Un code JavaScript malveillant peut être intégré à la page et le stockage Web est compromis. Ces types d'attaques XSS peuvent obtenir le stockage Web de tout le monde qui visite votre site, à leur insu. C'est probablement pourquoi de nombreuses organisations conseillent de ne rien stocker de valeur ou de ne faire confiance à aucune information dans le stockage Web. Cela inclut les identifiants de session et les jetons.

via Stormpath

Tout script dont vous avez besoin de l'extérieur pourrait potentiellement être compromis et récupérer n'importe quel JWTS du stockage de votre client et renvoyer des données personnelles au serveur de l'attaquant.

Stephen L
la source
6
Si je ne prévois pas d'utiliser cdns, est-ce que ce sera sans danger?
1
L'auteur de l'article n'a jamais fait de distinction entre XSS sur des sites servis via un CDN ou directement à partir d'un serveur central. Votre explication ici ne s'appliquerait-elle pas également en général, pas seulement pour les CDN?
Vlad
5

Localstorage est conçu pour être accessible par javascript, il ne fournit donc aucune protection XSS. Comme mentionné dans d'autres réponses, il existe un tas de façons possibles de faire une attaque XSS, contre laquelle le stockage local n'est pas protégé par défaut.

Cependant, les cookies ont des indicateurs de sécurité qui protègent des attaques XSS et CSRF. L'indicateur HttpOnly empêche le javascript côté client d'accéder au cookie, l'indicateur Secure permet uniquement au navigateur de transférer le cookie via SSL et l'indicateur SameSite garantit que le cookie est envoyé uniquement à l'origine. Bien que je viens de vérifier et que SameSite n'est actuellement pris en charge que dans Opera et Chrome, il est donc préférable d'utiliser d'autres stratégies pour se protéger du CSRF. Par exemple, envoyer un jeton chiffré dans un autre cookie avec des données utilisateur publiques.

Les cookies sont donc un choix plus sûr pour stocker les données d'authentification.

Ivan
la source
ne peut pas obtenir: comment HttpOnly peut vous protéger de CSRF?
Alex Lyalka
@AlexLyalka Ne voulait pas dire que HttpOnly empêche de CSRF, plutôt que tous les indicateurs de cookie ensemble peuvent protéger contre XSS et CSRF. SameSite offre une certaine protection, empêchant les cookies d'être envoyés à un site différent de l'origine. Bien que je viens de vérifier et que la prise en charge de cet indicateur soit très faible. Il est également possible d'éviter CSRF avec un jeton crypté séparé avec une identification d'utilisateur, qui est vérifiée sur le serveur.
Ivan
1
Eh bien, si quelqu'un peut exécuter du code sur votre site Web, ne peut-il pas simplement publier un message sur votre site Web au nom de votre utilisateur? Ok, il ne peut pas obtenir vos cookies http uniquement, mais il peut passer des appels en utilisant ces cookies, donc je ne vois toujours pas le point
Borja Alvarez
2
@BorjaAlverez Il y a une grande différence. Oui, via XSS, quelqu'un peut faire des demandes au nom de l'utilisateur connecté, mais compromettre un jeton est pire. Par exemple: le jeton peut fournir un accès aux API que l'application cliente n'utilise pas; le jeton peut contenir d'autres informations sur l'utilisateur (adresse e-mail, profil et subventions); le jeton pourrait être utilisé dans des attaques de relecture contre votre application; le jeton peut être passé en tant que id_token_hintserveur d'authentification OIDC; le jeton fournit à un attaquant des informations sur le chiffrement qui a été utilisé pour le signer; etc.
avejidah
3

Une façon de voir cela est de considérer le niveau de risque ou de préjudice.

Construisez-vous une application sans utilisateurs, POC / MVP? Êtes-vous une startup qui a besoin de se lancer sur le marché et de tester votre application rapidement? Si oui, je mettrais probablement en œuvre la solution la plus simple et je resterais concentré sur la recherche de produits adaptés au marché. Utilisez localStorage car il est souvent plus facile à implémenter.

Construisez-vous une version v2 d'une application avec de nombreux utilisateurs actifs quotidiens ou une application dont les personnes / entreprises dépendent fortement. Se faire pirater signifierait-il peu ou pas de place pour la récupération? Si tel est le cas, j'examinerais longuement vos dépendances et envisagerais de stocker les informations de jeton dans un cookie http uniquement.

L'utilisation à la fois de localStorage et de cookie / session de stockage a ses propres avantages et inconvénients.

Comme indiqué dans la première réponse: si votre application présente une vulnérabilité XSS, aucune des deux ne protégera votre utilisateur. Étant donné que la plupart des applications modernes ont une douzaine de dépendances différentes ou plus, il devient de plus en plus difficile de garantir qu'une des dépendances de votre application n'est pas vulnérable à XSS.

Si votre application présente une vulnérabilité XSS et qu'un pirate informatique a pu l'exploiter, le pirate informatique pourra effectuer des actions au nom de votre utilisateur. Le pirate informatique peut effectuer des requêtes GET / POST en récupérant le jeton de localStorage ou peut effectuer des requêtes POST si le jeton est stocké dans un cookie http uniquement.

Le seul inconvénient du stockage de votre jeton dans le stockage local est que le pirate pourra lire votre jeton.

HenokG
la source
1

Le cookie localStorage ou httpOnly n'est-il pas acceptable? En ce qui concerne une bibliothèque tierce compromise, la seule solution que je connaisse qui réduira / empêchera le vol d'informations sensibles serait l'application de l' intégrité des sous-ressources .

L'intégrité des sous-ressources (SRI) est une fonction de sécurité qui permet aux navigateurs de vérifier que les ressources qu'ils récupèrent (par exemple, à partir d'un CDN) sont livrées sans manipulation inattendue. Cela fonctionne en vous permettant de fournir un hachage cryptographique auquel une ressource extraite doit correspondre.

Tant que la bibliothèque tierce compromise est active sur votre site Web, un keylogger peut commencer à collecter des informations telles que le nom d'utilisateur, le mot de passe et tout ce que vous saisissez sur le site.

Un cookie httpOnly empêchera l'accès depuis un autre ordinateur mais ne fera rien pour empêcher le pirate de manipuler l'ordinateur de l'utilisateur.

SILENCIEUX
la source
-10

Vous pouvez stocker votre jeton en toute sécurité dans localStorage tant que vous le chiffrez. Vous trouverez ci-dessous un extrait de code compressé montrant l'une des nombreuses façons de le faire.

    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);
     }

Ensuite, avant d'utiliser votre token, décryptez-le en utilisant PRIVATE_KEY_STORED_IN_ENV_FILE

Kidali Kevin
la source
@HassanAlthaf vous manquez le point ici, il n'y aura jamais d'application de preuve 100% sécurisée, c'est juste que vous réduisez la surface d'attaque et au moins le fichier env ne sera pas publié directement sur github. En outre, le code fourni sera obscurci et mutilé, ce qui rendra difficile pour les attaquants de les trouver.
Kidali Kevin
La clé privée n'est pas censée être exposée. Vous compromettriez l'ensemble de l'API.
Hassan Althaf
D'après mon expérience Si vous avez fait les choses intelligemment et correctement, votre clé privée ne sera pas exposée dans votre version de production, si c'est le cas, une capture d'écran pour prendre en charge ceci ou même une URL.
Kidali Kevin