Onde armazenar o JWT no navegador? Como se proteger contra o CSRF?

159

Eu sei autenticação baseada em cookie. Os sinalizadores SSL e HttpOnly podem ser aplicados para proteger a autenticação baseada em cookie do MITM e XSS. No entanto, serão necessárias medidas mais especiais a fim de protegê-lo do CSRF. Eles são um pouco complicados. ( referência )

Recentemente, descobri que o JSON Web Token (JWT) é bastante quente como uma solução para autenticação. Conheço os detalhes sobre codificação, decodificação e verificação do JWT. No entanto, não entendo por que alguns sites / tutoriais não exigem proteção CSRF se o JWT for usado. Eu li bastante e tentei resumir os problemas abaixo. Eu só quero que alguém possa fornecer uma visão geral do JWT e esclarecer os conceitos que eu não entendi sobre o JWT.

  1. Se o JWT estiver armazenado no cookie, acho que é o mesmo que autenticação baseada em cookie, exceto que o servidor não precisa ter sessões para verificar o cookie / token. Ainda existe risco sobre o CSRF se nenhuma medida especial for implementada. O JWT não está armazenado no cookie?

  2. Se o JWT estiver armazenado em localStorage / sessionStorage, nenhum cookie será necessário, portanto não será necessário proteger contra o CRSF. A questão é como enviar o JWT para o servidor. Eu encontrei aqui sugere o uso do jQuery para enviar o cabeçalho JWT por HTTP das solicitações ajax. Então, apenas as solicitações ajax podem fazer a autenticação?

  3. Além disso, encontrei mais um programa de blog para usar "Cabeçalho de autorização" e "Portador" para enviar o JWT. Eu não entendo o método que o blog fala. Alguém poderia explicar mais sobre "Cabeçalho da autorização" e "Portador"? Isso faz com que o JWT transmitido pelo cabeçalho HTTP de TODAS as solicitações? Se sim, e o CSRF?

Timespace7
fonte

Respostas:

70

Os tokens JWT são populares, pois são usados ​​como formato padrão de token em novos protocolos de autorização e autenticação, como OAuth 2.0 e OpenID Connect .

Quando o token é armazenado em um cookie, o navegador o envia automaticamente juntamente com cada solicitação para o mesmo domínio e isso ainda é vulnerável a ataques de CSRF.

A autenticação do portador é um dos esquemas de autenticação definidos no HTTP. Basicamente, isso significa que YOUcola o token (JWT) no cabeçalho HTTP de autorização de uma solicitação. O navegador fará NOTisso por você automaticamente, portanto, não é adequado para proteger seu site. Como o navegador não adiciona automaticamente o cabeçalho à sua solicitação, ele não é vulnerável a um ataque de CSRF, que depende de suas informações de autenticação serem enviadas automaticamente para o domínio original.

O esquema do portador é frequentemente usado para proteger APIs da web (serviços REST) ​​que são consumidas por chamadas AJAX ou de clientes móveis.

MvdD
fonte
1
@ Timespace7 Não, os tokens JWT também são frequentemente usados ​​em clientes nativos. O OAuth 2.0 possui fluxos direcionados especificamente para clientes nativos (móveis). O que eles não fazem é a autenticação implícita do navegador (como cookies ou autenticação básica).
MTVD
5
Estou dizendo que, se sua API recuperar apenas o token JWT do cabeçalho de autorização, não estará vulnerável ao CSRF. Qualquer site ou API que obtenha o token de um cookie precisa de mitigação de CSRF.
MvdD 25/03
13
Isso significa que podemos armazenar efetivamente o jwt em um cookie e ele será seguro se enviarmos solicitações com ele no cabeçalho da Autorização?
Cameronroe
10
@cameronjroe você pode armazená-lo em seus cookies, mas somente se você não usar os cookies para autenticação (você usa seus cabeçalhos neste caso)
Jaakko
1
As chamadas AJAX também são originárias do navegador. Fichas JWT são usados principalmente para APIs autenticar Web (serviço de dados) vs cookies utilizados para aplicativos autenticar Web (serviço de marcação, imagens, CSS e JavaScript)
MvdD
143

Precisamos armazenar o JWT no computador cliente. Se o armazenarmos em um LocalStorage / SessionStorage, ele poderá ser facilmente capturado por um ataque XSS. Se o armazenarmos em cookies, um hacker poderá usá-lo (sem lê-lo) em um ataque CSRF e personificar o usuário e entrar em contato com nossa API e enviar solicitações para executar ações ou obter informações em nome de um usuário.

Mas existem várias maneiras de proteger o JWT nos cookies para não serem roubados facilmente (mas ainda existem algumas técnicas avançadas para roubá-los). Mas se você quiser confiar no LocalStorage / SessionStorage, ele poderá ser acessado por um simples ataque XSS.

Portanto, para resolver o problema do CSRF, uso Cookies de envio duplo no meu aplicativo.

Método de envio duplo de cookies

  1. Armazene o JWT em um cookie HttpOnly e use-o no modo seguro para transferir por HTTPS.

  2. A maioria dos ataques de CSRF tem uma origem ou cabeçalho de referência diferente com o host original em suas solicitações. Portanto, verifique se você tem algum deles no cabeçalho, eles são provenientes do seu domínio ou não! Caso contrário, rejeite-os. Se a origem e o referenciador não estiverem disponíveis na solicitação, não se preocupe. Você pode confiar no resultado dos resultados da validação de cabeçalho X-XSRF-TOKEN, que explicarei na próxima etapa.

  3. Embora o navegador forneça automaticamente seus cookies para o domínio da solicitação, há uma limitação útil: o código JavaScript que está sendo executado em um site não pode ler os cookies de outros sites. Podemos aproveitar isso para criar nossa solução CSRF. Para evitar ataques CSRF, precisamos criar um cookie legível em Javascript extra chamado: XSRF-TOKEN. Esse cookie deve ser criado quando o usuário estiver conectado e deve conter uma sequência aleatória e impossível de adivinhar. Também salvamos esse número no próprio JWT como uma reivindicação privada. Sempre que o aplicativo JavaScript desejar fazer uma solicitação, precisará ler esse token e enviá-lo em um cabeçalho HTTP personalizado. Como essas operações (leitura do cookie, configuração do cabeçalho) só podem ser realizadas no mesmo domínio do aplicativo JavaScript,

JS angular facilita sua vida

Felizmente, estou usando o Angular JS em nossa plataforma e os pacotes Angular, a abordagem de token CSRF, tornando mais simples a implementação. Para cada solicitação que nosso aplicativo Angular fizer do servidor, o $httpserviço Angular fará essas coisas automaticamente:

  • Procure um cookie chamado XSRF-TOKEN no domínio atual.
  • Se esse cookie for encontrado, ele lê o valor e o adiciona à solicitação como cabeçalho X-XSRF-TOKEN.

Assim, a implementação do lado do cliente é tratada automaticamente para você! Nós apenas precisamos definir um cookie nomeado XSRF-TOKENno domínio atual no lado do servidor e, quando nossa API receber qualquer chamada do cliente, ela deverá verificar o X-XSRF-TOKENcabeçalho e compará-lo com XSRF-TOKENo JWT. Se eles corresponderem, o usuário será real. Caso contrário, é uma solicitação forjada e você pode ignorá-la. Este método é inspirado no método "Double Submit Cookie".

Cuidado

Na realidade, você ainda é suscetível ao XSS, mas o invasor não pode roubar seu token JWT para uso posterior, mas ele ainda pode fazer solicitações em nome de seus usuários usando o XSS.

Se você armazena seu JWT no localStorageou armazena seu token XSRF no cookie HttpOnly, ambos podem ser facilmente capturados pelo XSS. Até o seu JWT em um cookie HttpOnly pode ser capturado por um ataque XSS avançado, como o método XST .

Portanto, além do método de envio duplo de cookies, você deve sempre seguir as práticas recomendadas contra o XSS, incluindo o escape de conteúdo. Isso significa remover qualquer código executável que faça com que o navegador faça algo que você não deseja. Normalmente, isso significa remover // <![CDATA[tags e atributos HTML que fazem com que o JavaScript seja avaliado.

Leia mais aqui:

Iman Sedighi
fonte
1
@AranDehkharghani sim, acho que evita ataques de repetição, especialmente se você alterar o JWT e expirar o JWT anterior toda vez que for usado pela API. isso significa que seu JWT se tornará uma senha descartável (OTP). Você pode usar o JWT de maneiras diferentes, dependendo de quanto você se preocupa com a segurança em sua plataforma.
Iman Sedighi
7
Como você mencionou, se um site é vulnerável ao XSS, é apenas uma questão de tempo até que o usuário seja explorado. Parece que estamos negociando complexidade significativa por um aumento muito pequeno na segurança.
shusson
3
@shusson Você deve cuidar dos ataques XSS e XSRF para proteger seu JWT. Não concordo que você esteja trocando complexidade significativa por um aumento muito pequeno na segurança. Se a segurança for importante, você precisará envidar todos os esforços para não ter vulnerabilidades XSS. Este método foi projetado para proteger seu token contra ataques XSRF. mas isso não significa que você pode ignorar as vulnerabilidades do XSS.
Iman Sedighi
5
@ImanSedighi Eu não estava claro, ao armazenar o jwt em um cookie, você adiciona complexidade e agora precisa se proteger contra o XSRF. Então, por que não usar o armazenamento local com tokens de vida curta e se concentrar na prevenção do XSS?
shusson
2
@Royi Namir: Spoofing by Wireshark não deve ser uma preocupação se você usar um certificado SSL de US $ 10! Se a segurança do site for importante, você deve criptografar os dados e usar o protocolo HTTPS.
Iman Sedighi
2

Outro ângulo para toda a questão do armazenamento de JWTs:

  1. Os JWTs nunca devem ser armazenados no seu localStorage
  2. De fato, eles nem deveriam ser armazenados em seus cookies , a menos que você possa implementar uma proteção CSRF muito rigorosa

Checkout isto para motivação

  • JWT como um id_token é como suas credenciais de usuário
  • O JWT como access_token é como seu token de sessão

A opção mais segura está na memória . Faça o checkout para um mergulho profundo

humano
fonte