É seguro armazenar um jwt no localStorage com reactjs?

147

Atualmente, estou criando um aplicativo de página única usando reactjs. Eu li que muitos dos motivos para não usar o localStorage são por causa das vulnerabilidades do XSS. Como o React escapa a todas as entradas do usuário, agora seria seguro usar o localStorage?

Kaloyan Kosev
fonte
4
prefere Session Storage
Praneet Rohida
3
"É recomendável não armazenar informações confidenciais no armazenamento local". -OWASP "armazena-os na memória sem persistência" -Auth0
avejidah
Acho Auth0 pode ter mudado sua perspectiva sobre isso - porque não consigo encontrar a citação acima no link fornecido
DauleDK

Respostas:

141

Na maioria dos aplicativos modernos de página única, precisamos armazenar o token em algum lugar do lado do cliente (caso de uso mais comum - para manter o usuário conectado após uma atualização da página).

Há um total de 2 opções disponíveis: Armazenamento na Web (armazenamento de sessão, armazenamento local) e um cookie do lado do cliente. Ambas as opções são amplamente usadas, mas isso não significa que elas são muito seguras.

Tom Abbott resume bem a segurança sessionStorage e localStorage do JWT :

O armazenamento na Web (localStorage / sessionStorage) pode ser acessado por meio de JavaScript no mesmo domínio. Isso significa que qualquer JavaScript em execução no seu site terá acesso ao armazenamento na Web e, por isso, pode ser vulnerável a ataques de script entre sites (XSS) . Em resumo, o XSS é um tipo de vulnerabilidade em que um invasor pode injetar JavaScript que será executado na sua página. Os ataques XSS básicos tentam injetar JavaScript através de entradas de formulário, onde o invasor o coloca <script>alert('You are Hacked');</script>em um formulário para ver se ele é executado pelo navegador e pode ser visualizado por outros usuários.

Para evitar o XSS, a resposta comum é escapar e codificar todos os dados não confiáveis. Reagir (principalmente) faz isso por você! Aqui está uma ótima discussão sobre a responsabilidade pela qual a proteção contra vulnerabilidades XSS é responsável pelo React .

Mas isso não cobre todas as vulnerabilidades possíveis! Outra ameaça em potencial é o uso de JavaScript hospedado em CDNs ou em infraestrutura externa .

Aqui está o Tom novamente:

Os aplicativos da Web modernos incluem bibliotecas JavaScript de terceiros para testes A / B, análise de funil / mercado e anúncios. Usamos gerenciadores de pacotes como o Bower para importar o código de outras pessoas em nossos aplicativos.

E se apenas um dos scripts que você usa estiver comprometido? JavaScript malicioso pode ser incorporado na página e o armazenamento na Web é comprometido. Esses tipos de ataques XSS podem obter o armazenamento na Web de todos que visitam seu site, sem o conhecimento deles. É provavelmente por isso que várias organizações aconselham a não armazenar nada de valor ou confiar em qualquer informação no armazenamento na web. Isso inclui identificadores de sessão e tokens.

Portanto, minha conclusão é que, como mecanismo de armazenamento, o Armazenamento na Web não impõe nenhum padrão seguro durante a transferência . Quem lê o Armazenamento da Web e o utiliza deve fazer a devida diligência para garantir que sempre envie o JWT por HTTPS e nunca por HTTP.

Kaloyan Kosev
fonte
10
Então, se estou entendendo corretamente, você recomenda cookies? Apenas para ter certeza. Obrigado!
SuperLemon 29/09
7
Sim. Eu recomendo cookies por causa da segurança adicional que eles fornecem e da simplicidade de proteção contra o CSRF com estruturas da Web modernas. O armazenamento na Web (localStorage / sessionStorage) é vulnerável ao XSS, possui uma área de superfície de ataque maior e pode afetar todos os usuários do aplicativo em um ataque bem-sucedido.
Kaloyan Kosev 29/09
48
Eu acho que você misturou isso? As estruturas da web modernas têm fortes defesas internas para o XSS. Mas não tanto para xsrf. A melhor defesa para o xsrf é evitar o uso completo de cookies. O armazenamento local é protegido por sandbox para um domínio específico, o que significa que o domínio do invasor não pode acessá-lo. As estruturas da Web se defendem contra o xss codificando e sanatizando automaticamente a entrada do usuário. Veja angular.io/guide/security
mikejones1477
47
Se "você recomenda cookies [em vez]]", posso recomendar que você diga isso em algum lugar da resposta? Em vez de apenas nos comentários?
spechter 15/05/19
7
Estou aqui um pouco atrasado, apenas lendo esses tópicos agora e estou confuso sobre uma coisa, muitas pessoas falam sobre você está protegido com um cookie apenas http se você estiver comprometido com o Xss, mas, se você tiver xss o atacante não precisa roubar nada, ele pode simplesmente fazer uma postagem na página para se passar por você usando esse cookie (mesmo que ele não possa roubá-lo). Estou esquecendo de algo???
Borja Alvarez
35

Eu sei que essa é uma pergunta antiga, mas de acordo com o que o @ mikejones1477 disse, as bibliotecas e estruturas modernas de front-end escapam do texto, oferecendo proteção contra o XSS. A razão pela qual os cookies não são um método seguro usando credenciais é que os cookies não impede CSRF quando localStorage não (também lembrar que os cookies são acessíveis por javascript também, então XSS não é o grande problema aqui), esta resposta currículo por isso .

O motivo para armazenar um token de autenticação no armazenamento local e adicioná-lo manualmente a cada solicitação protege contra CSRF é essa palavra-chave: manual. Como o navegador não envia automaticamente esse token de autenticação, se eu visitar evil.com e ele conseguir enviar um POST http://example.com/delete-my-account , ele não poderá enviar meu token de autenticação, portanto a solicitação é ignorada.

É claro que httpOnly é o santo graal, mas você não pode acessar a partir do reactjs ou de qualquer estrutura js ao lado de você ainda tem vulnerabilidade CSRF. Minha recomendação seria armazenamento local ou, se você quiser usar cookies, certifique-se de implementar alguma solução para o seu problema de CSRF, como o django .

Com relação às CDNs, verifique se você não está usando CDNs estranhas, por exemplo, CDNs como o google ou o bootstrap fornecem, são mantidas pela comunidade e não contêm código malicioso, se você não tiver certeza, pode revisar.

Mauricio Cortazar
fonte
2
Não sei por que você diria que ainda está vulnerável ao CSRF ao usar cookies. Usando um cookie com as bandeiras HttpOnly SameSite=stricte secure, manterá segura as informações que você definir nos cookies. Em relação ao XSS, você simplesmente garante que o JavaScript não tenha conhecimento de dados relacionados à autenticação, como tokens e senhas (ou seja, não os armazene no Armazenamento na Web) - se você importar um script mal-intencionado, esse script não terá acesso para dados confidenciais. Sim, você também não terá acesso ao token através do JS, mas isso realmente não deve ser um problema.
Miphe
@ miphe foi o que eu disse. Mas o OP está pedindo uma maneira de acessar a partir de javascript. Aqui estou apenas explicando qual é a melhor maneira de armazenar um token acessível a partir de js.
Mauricio Cortazar
21

Basicamente, não há problema em armazenar seu JWT em seu localStorage.

E acho que esse é um bom caminho. Se estamos falando de XSS, XSS usando CDN, também é um risco potencial de obter o login / senha do seu cliente também. Armazenar dados no armazenamento local impedirá pelo menos ataques de CSRF.

Você precisa conhecer os dois e escolher o que deseja. Ambos os ataques não são tudo o que você precisa saber, lembre-se: SEU APLICATIVO INTEIRO É TÃO SEGURO COMO O PONTO MAIS SEGURO DO APLICATIVO.

Mais uma vez, o armazenamento está OK, seja vulnerável a XSS, CSRF, ... não

Alex Lyalka
fonte
2
É por isso que é seguro fazer o seguinte: - Armazenar o JWT em um cookie para que não possa ser recuperado do XSS - Armazenar um token CSRF no localStorage para que não possa ser recuperado do CSRF
Alejandro Cavazos
33
Você mencionou um bom ponto: se o site executar um script malicioso, o jogo terminará assim mesmo. Eles podem simplesmente vincular eventos de keydown a entradas do tipo senha e roubar as informações de autenticação do usuário dessa maneira (o que é muito, muito pior do que roubar um token de autenticação JWT). Armazenar JWTs no localStorage faz pouco para aumentar o imenso dano possível do XSS.
precisa
8

Não é seguro se você usar CDNs:

JavaScript malicioso pode ser incorporado na página e o armazenamento na Web é comprometido. Esses tipos de ataques XSS podem obter o armazenamento na Web de todos que visitam seu site, sem o conhecimento deles. É provavelmente por isso que várias organizações aconselham a não armazenar nada de valor ou confiar em qualquer informação no armazenamento na web. Isso inclui identificadores de sessão e tokens.

via stormpath

Qualquer script que você exija externamente pode ser comprometido e pode pegar qualquer JWTS do armazenamento do seu cliente e enviar dados pessoais de volta ao servidor do invasor.

Stephen L
fonte
6
Se eu não planejar usar o cdns, será seguro?
1
O autor do artigo nunca fez uma distinção entre XSS em sites servidos por uma CDN ou diretamente de um servidor central. Sua explicação aqui também não se aplicaria geralmente, não apenas às CDNs?
Vlad
5

O Localstorage foi projetado para ser acessível por javascript, portanto, não fornece nenhuma proteção XSS. Como mencionado em outras respostas, existem várias maneiras possíveis de realizar um ataque XSS, do qual o armazenamento local não é protegido por padrão.

No entanto, os cookies possuem sinalizadores de segurança que protegem contra ataques XSS e CSRF. O sinalizador HttpOnly impede que o javascript do lado do cliente acesse o cookie, o sinalizador seguro permite apenas que o navegador transfira o cookie por ssl, e o sinalizador SameSite garante que o cookie seja enviado apenas para a origem. Embora eu tenha acabado de verificar e o SameSite atualmente seja suportado apenas no Opera e no Chrome, para proteger do CSRF, é melhor usar outras estratégias. Por exemplo, enviando um token criptografado em outro cookie com alguns dados públicos do usuário.

Portanto, os cookies são uma opção mais segura para armazenar dados de autenticação.

Ivan
fonte
não é possível obter: como o HttpOnly pode protegê-lo do CSRF?
precisa saber é o seguinte
@AlexLyalka Não quis dizer que o HttpOnly impede o CSRF, em vez de todos os sinalizadores de cookies juntos protegerem contra o XSS e o CSRF. SameSite fornece alguma proteção, impedindo que os cookies sejam enviados para um site diferente da origem. Embora eu tenha acabado de verificar e o suporte para essa bandeira seja muito baixo. Também é possível evitar o CSRF com um token criptografado separado com alguma identificação do usuário, que é verificada no servidor.
Ivan
1
Bem, se alguém pode executar código na sua web, ele não pode simplesmente postar na web em nome do seu usuário? Ok, ele não pode obter o seu http apenas cookies, mas ele pode fazer chamadas usando esses cookies, então eu ainda não posso ver o ponto
Borja Alvarez
2
@BorjaAlverez Há uma grande diferença. Sim, via XSS alguém poderia fazer solicitações em nome do usuário conectado, mas comprometer um token é pior. Por exemplo: o token pode fornecer acesso a APIs que o aplicativo cliente não usa; o token pode ter outras informações sobre o usuário (endereço de email, perfil e concessões); o token pode ser usado em ataques de repetição contra seu aplicativo; o token pode ser passado como um id_token_hintservidor de autenticação OIDC; o token fornece ao invasor informações sobre a cifra usada para assiná-lo; etc
avejidah 5/08/19
3

Uma maneira de analisar isso é considerar o nível de risco ou dano.

Você está criando um aplicativo sem usuários, POC / MVP? Você é uma startup que precisa chegar ao mercado e testar seu aplicativo rapidamente? Se sim, eu provavelmente implementaria a solução mais simples e manteria o foco em encontrar o ajuste do produto ao mercado. Use localStorage como geralmente mais fácil de implementar.

Você está criando uma versão 2 de um aplicativo com muitos usuários ativos diários ou um aplicativo do qual as pessoas / empresas dependem bastante. Ser hackeado significaria pouco ou nenhum espaço para recuperação? Nesse caso, examinaria suas dependências e consideraria o armazenamento de informações de token em um cookie somente http.

O uso do localStorage e do armazenamento de cookies / sessões tem seus próprios prós e contras.

Conforme declarado pela primeira resposta: se o seu aplicativo tiver uma vulnerabilidade XSS, nenhum deles protegerá o usuário. Como a maioria dos aplicativos modernos tem uma dúzia ou mais de dependências diferentes, torna-se cada vez mais difícil garantir que uma das dependências do aplicativo não seja vulnerável ao XSS.

Se o seu aplicativo tiver uma vulnerabilidade XSS e um hacker puder explorá-lo, o hacker poderá executar ações em nome do seu usuário. O hacker pode executar solicitações GET / POST recuperando o token do localStorage ou pode executar solicitações POST se o token estiver armazenado em um cookie somente http.

A única desvantagem de armazenar seu token no armazenamento local é que o hacker poderá ler seu token.

HenokG
fonte
1

O cookie localStorage ou httpOnly não é aceitável? No que diz respeito a uma biblioteca de terceiros comprometida, a única solução que eu conheço que reduzirá / impedirá que informações confidenciais sejam roubadas seria imposta à Integridade de Sub-recursos .

SRI (Subresource Integrity) é um recurso de segurança que permite que os navegadores verifiquem se os recursos que eles buscam (por exemplo, de uma CDN) são entregues sem manipulação inesperada. Ele funciona permitindo que você forneça um hash criptográfico ao qual um recurso buscado deve corresponder.

Enquanto a biblioteca de terceiros comprometida estiver ativa no seu site, um keylogger poderá começar a coletar informações como nome de usuário, senha e qualquer outra coisa que você inserir no site.

Um cookie httpOnly impedirá o acesso de outro computador, mas não fará nada para impedir que o hacker manipule o computador do usuário.

SILENT
fonte
-10

É seguro armazenar seu token no localStorage enquanto você o criptografar. Abaixo está um trecho de código compactado mostrando uma das muitas maneiras de fazer isso.

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

Antes de usar seu token, decifre-o usando PRIVATE_KEY_STORED_IN_ENV_FILE

Kidali Kevin
fonte
@HassanAlthaf, se você está perdendo o objetivo aqui, nunca haverá um aplicativo de prova 100% seguro. É só isso, você está reduzindo a superfície de ataque e pelo menos o arquivo env não será publicado diretamente no github. Além disso, o código incluído será ofuscado e mutilado, dificultando a localização dos atacantes.
Kidali Kevin 11/12/19
A chave privada não deve ser exposta. Você comprometeria toda a API.
Hassan Althaf 12/12/19
Da minha experiência Se você fez as coisas de maneira inteligente e correta, sua chave privada não será exposta na sua produção, se sim, na captura de tela para dar suporte a esse ou mesmo a um URL.
Kidali Kevin