Divida um JWT entre carga útil e assinatura
Contexto: Estou procurando soluções de armazenamento para tokens JWT em um aplicativo de página única.
- Armazenar o JWT no armazenamento local não é seguro e está sujeito a ataques XSS.
- Armazenar o JWT em um cookie seguro / apenas HTTP é mais seguro, mas sujeito a ataques CSRF.
Estou estudando o seguinte cenário:
Após a autenticação, um token de atualização é armazenado em um cookie seguro apenas http. Ele só pode ser usado para obter um token de acesso.
Após a autorização, o back-end responde com um token de acesso JWT. O cabeçalho e a parte da carga útil do JWT estão dentro do corpo da resposta. A assinatura do token não é enviada e é definida em um cookie seguro apenas http (mesmo site estrito, se possível, mas vamos supor que não seja o caso). O cabeçalho + carga útil é armazenado na memória.
O JWT contém as seguintes reivindicações
- iat, nbf, exp (IMO deduzível)
- declarações relativas à identidade e às permissões do usuário (adivinhadas se a identidade do usuário for conhecida)
- jti, contendo um número aleatório criptograficamente seguro (no meu caso gerado com segredos python )
Ao fazer solicitações, o cabeçalho + carga útil é enviado via XHR / busca pelo SPA em um cabeçalho de Autorização. A assinatura é enviada junto com os cookies. O back-end concatena e verifica a assinatura.
- Este mecanismo é seguro contra ataques CSRF? As declarações jti tornam o token de autorização + cookie de assinatura uma técnica válida de mitigação de CSRF?
- Esse mecanismo é realmente mais seguro contra ataques XSS do que armazenar o JWT dentro do armazenamento local? (Pode um ataque usando XSS também roubar facilmente a assinatura, como com um exploit TRACE ).
Observação: eu li essa pergunta que é semelhante, mas muito ampla, então estou postando para obter uma resposta mais precisa.
Respostas
Este mecanismo é seguro contra ataques CSRF?
Este método de dividir um JWT e armazenar a assinatura no cookie e o resto do token no armazenamento do navegador não fornece nenhuma proteção adicional contra ataques CSRF do que se todo o JWT fosse armazenado no armazenamento local ou de sessão. Sim, isso atenuará os ataques de CSRF, mas você não precisa adicionar a sobrecarga desnecessária de dividir e concatenar JWTs no servidor. Armazenar JWTs no armazenamento local e aceitá-los apenas nos cabeçalhos de autorização é o suficiente para proteger seu aplicativo de ataques CSRF.
Esse mecanismo é realmente mais seguro contra ataques XSS do que armazenar o JWT dentro do armazenamento local? (Pode um ataque usando XSS também roubar facilmente a assinatura, como com uma exploração TRACE)
Se o seu foco for apenas um invasor capaz de roubar JWTs, essa abordagem é segura, a menos que, como você corretamente mencionou, o TRACE esteja ativado no servidor.
No entanto, isso não torna seu aplicativo mais seguro contra ataques XSS. Por exemplo, se eu conseguir executar Javascript arbitrário em seu aplicativo, posso buscar o cabeçalho JWT + carga útil do armazenamento local e apenas enviar um XHR para um ponto de extremidade sensível mantendo withCredentials definido como True. Este endpoint pode ser projetado para alterar o endereço de e-mail da conta, por exemplo. Isso leva imediatamente a uma apropriação da conta. Não há necessidade de roubar cookies ou JWTs.
Resumindo: essa abordagem fornece alguma proteção contra tokens de sessão, separando a assinatura do restante do token. No entanto, quando se trata de XSS, roubar tokens de sessão não é o único risco que você deve examinar.