JSON Web Token e a importância do Tempo de Expiração

Picture of Júlia Valim

Júlia Valim

JSON Web Token

O que é JSON Web Token?

O JWT (JSON Web Token) é um padrão para autenticação e troca de informações que foi documentado pela RFC7519. Nele é possível armazenar objetos JSON de uma forma que seja segura e compacta, sendo encodado em Base64 e podendo ser assinado por chaves públicas ou privadas.

É muito utilizado para validar serviços em Web Services, pois os dados no token podem ser validados a qualquer momento por conta da assinatura.

Estrutura do JSON Web Token

A estrutura de um token JWT é composta por 3 partes principais: Cabeçalho, Payload e Assinatura.

Cabeçalho:

O cabeçalho define o tipo do token e o algoritmo de criptografia utilizado para a assinatura. Normalmente, contém dois campos:

  • alg: Especifica o algoritmo de assinatura (por exemplo, HMAC SHA256 ou RSA).
  • typ: Define o tipo de token, que geralmente é “JWT”.

Payload:

O payload contém as reivindicações (claims), que são informações sobre a entidade (geralmente o usuário) e outros dados adicionais. Existem três tipos de reivindicações:

  • Registradas: Pré-definidas e com um significado específico (como sub para o assunto, iat para a data de emissão).
  • Públicas: Definidas pelo usuário, mas com o risco de colisão de nome.
  • Privadas: Criadas para compartilhar informações entre partes que concordam sobre seu uso.

Assinatura:

A assinatura é gerada a partir do cabeçalho e do payload, utilizando o algoritmo definido no cabeçalho. Ela é usada para verificar a integridade do token e garantir que o conteúdo não foi alterado. Caso o conteúdo do token seja modificado, a assinatura será invalidada, ajudando a proteger o JWT contra alterações não autorizadas.

Estrutura JSON Web Token

Figura: Estrutura JSON Web Token

Exemplo de Token

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Separado desta forma, temos:

Header

Payload

Assinatura

Através do site jwt.io, podemos verificar de uma forma mais didática o mesmo token:

Token JWT

Figura: Token JWT

Dentro de Header, podemos verificar que possui alg e typ, indicando que é um token JWT e o seu algoritmo utilizado na assinatura.

Header

Figura: Header

Agora em Payload, temos sub, que se refere ao identificador do usuário. No caso do name, ela não é uma claim oficial do JWT, mas sim criada e personalizada conforme a necessidade do desenvolvedor. Neste caso em específico, ela serve para armazenar o nome a quem o token pertence. Já o iat refere-se “Issued at”, ou seja, quando o token foi emitido.

Payload

Figura: Payload

Por fim, dentro de Signature, temos a concatenação dos hashes gerados a partir do Header e Payload usando base64UrlEncode, com uma chave secreta ou certificado RSA.

Signature

Figura: Signature

Fluxo de Autenticação

O fluxo de autenticação do token JWT funciona da seguinte maneira:

  1. O usuário faz login no sistema fornecendo suas credenciais (por exemplo, nome de usuário e senha). O servidor, após verificar essas credenciais, gera um JWT contendo as informações do usuário (payload) e uma assinatura para garantir a autenticidade e a integridade dos dados.
  2. O servidor envia o JWT gerado de volta ao cliente (como o navegador ou aplicativo). O token é geralmente armazenado no cliente em um local seguro, como cookies ou no armazenamento local, para uso em solicitações futuras.
  3. A cada requisição subsequente feita pelo cliente (por exemplo, para acessar páginas protegidas ou APIs), o cliente envia o JWT de volta ao servidor, geralmente no cabeçalho da requisição HTTP (por exemplo, Authorization: Bearer <JWT>).
  4. O servidor valida a assinatura do JWT usando a chave secreta ou chave pública associada. Isso garante que o token não foi alterado desde sua emissão. Além disso, o servidor pode verificar o tempo de expiração do token (se estiver presente) para garantir que o token ainda é válido. Se a assinatura for válida e o token não expirou, o servidor permite o acesso aos recursos solicitados.

Fluxo de autenticação de JWT

Figura: Fluxo de autenticação

Caso Real

Durante um pentest solicitado pela empresa Acme, um de nossos pentesters encontrou e reportou uma vulnerabilidade dentro do JWT da aplicação da empresa, mais especificamente no payload do JSON Web Token.

O payload deste JSON Web Token não possuía todas as Reserved Claims (atributos recomendados para maior segurança), como o exp (expiration). Ou seja, quando um token não possui o atributo “exp”, ele não expira, representando diversas vulnerabilidades críticas para a aplicação. Quando um token não possui um tempo de expiração, ele é vulnerável a vários riscos de segurança, como:

O token se torna permanente, o que significa que, se for comprometido por um atacante em algum momento, poderá ser utilizado indefinidamente para acessar recursos protegidos.

Reutilização, uma vez que pode ocorrer de ele ser capturado e reutilizado por um atacante mal-intencionado antes do usuário, levando a acessos não autorizados e comprometimento de dados.

Mais a fundo no JWT

Porém, neste mesmo pentest com o objetivo de ir mais a fundo nesta vulnerabilidade e explorá-la ainda mais, o pentester buscou meios de encontrar vazamentos dos tokens em plataformas externas, tais como GitHub.

Neste trabalho de busca foi encontrado mais de 70 possíveis tokens vazados e que posteriormente foram validados.

Abaixo estão as evidências das descobertas realizadas:

Vazamento token no GitHub 1

Figura: Vazamento token no GitHub 1

Validação Token

Figura: Validação Token

Vazamento token no GitHub 2

Figura: Vazamento token no GitHub 2

Validação Token JWT

Figura: Validação Token

Vazamento token no GitHub 3

Figura: Vazamento token no GitHub 3

Validação Token

Figura: Validação Token

Através dessas evidências um atacante poderia utilizar estes tokens para conseguir coletar informações de clientes ou cometer fraudes, devido também a quantidade de tokens expostos a vulnerabilidade é classificada como crítica.

Recomendação

A recomendação feita é de que seja implementado o recurso de expiração dentro do token, pois através deste atributo o risco apresentado a aplicação seria bem menor. Para incluir este recurso basta acrescentar dentro do campo payload a claim exp + tempo (em segundos) que deseja para expirar, como podemos ver no exemplo a seguir:

Validação JSON Web Token

Figura: Payload JWT

Conforme as boas práticas, os tokens de acesso devem ter um período de expiração relativamente curto, geralmente variando entre 15 minutos e 1 hora, a fim de minimizar riscos de segurança em caso de comprometimento. Além disso, é recomendável que a aplicação implemente um token de atualização, pois isso facilita ainda mais a experiência do usuário, garantindo um processo de autenticação mais fluido e sem interrupções.

Os tokens de atualização (refresh tokens) devem ter um tempo de expiração mais longo, normalmente entre 1 dia e 1 semana. Isso ocorre porque os refresh tokens são usados para obter novos tokens de acesso e, portanto, devem ter uma duração mais longa para minimizar a necessidade de os usuários se reautenticarem com frequência.

No entanto, ambos os intervalos podem ser ajustados de acordo com as necessidades específicas da aplicação, levando em consideração fatores como a sensibilidade das operações realizadas e o equilíbrio entre segurança e experiência do usuário.

Por fim, além de configurar a expiração de tokens de acesso e refresh tokens, é fundamental contar com um sistema de revogação de tokens. Esse mecanismo garante que, em situações como logout, troca de senha ou suspeita de vazamento de credenciais, seja possível invalidar tokens ativos imediatamente, independentemente do prazo de expiração configurado. Uma abordagem comum envolve manter uma lista de tokens revogados em um repositório central, consultada a cada requisição feita ao servidor, de forma a impedir o uso de tokens que já não são mais confiáveis. Assim, a aplicação mantém um controle mais rigoroso sobre o ciclo de vida dos tokens, protegendo-se contra acessos indevidos e assegurando uma postura de segurança mais abrangente.

Conclusão

O JSON Web Token é uma tecnologia amplamente utilizada para autenticação e troca de dados de forma prática e segura. Entretanto, como demonstrado, é fundamental que os desenvolvedores observem as boas práticas de implementação, incluindo a configuração de tempo de expiração, adoção de algoritmos de criptografia robustos e o uso adequado de refresh tokens. O exemplo de pentest citado evidenciou a gravidade de se negligenciar essas recomendações, resultando em tokens com validade indefinida e potencial risco de vazamentos. Ao incorporar políticas de segurança, revisar periodicamente o código e monitorar possíveis exposições de credenciais, as empresas podem minimizar riscos e fortalecer a proteção de suas aplicações e dados sensíveis.

Referências

O que é JSON Web Tokens?

JWT attacks

JWT

JWT Security Best Practices

5 JWT authentication best practices for Node.js apps

Créditos

Heitor Gouvêa

Arthur Martins

veja também

Outros conteúdos sobre Segurança Cibernética