JWT Vulnerabilities (Json Web Tokens)
Last updated
Last updated
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Se você está interessado em carreira de hacking e hackear o inhackeável - estamos contratando! (fluência em polonês escrita e falada é necessária).
Parte deste post é baseada no ótimo post: https://github.com/ticarpi/jwt_tool/wiki/Attack-Methodology Autor da ótima ferramenta para pentest JWTs https://github.com/ticarpi/jwt_tool
Execute jwt_tool com o modo All Tests!
e aguarde linhas verdes.
Se você tiver sorte, a ferramenta encontrará algum caso em que a aplicação web está verificando incorretamente o JWT:
Então, você pode procurar a solicitação em seu proxy ou despejar o JWT usado para essa solicitação usando jwt_ tool:
Você também pode usar a Burp Extension SignSaboteur para lançar ataques JWT a partir do Burp.
Você pode apenas manipular os dados deixando a assinatura como está e verificar se o servidor está checando a assinatura. Tente mudar seu nome de usuário para "admin", por exemplo.
Para verificar se a assinatura de um JWT está sendo verificada:
Uma mensagem de erro sugere verificação em andamento; detalhes sensíveis em erros verbosos devem ser revisados.
Uma mudança na página retornada também indica verificação.
Nenhuma mudança sugere nenhuma verificação; é quando se deve experimentar com a manipulação das reivindicações do payload.
É importante determinar se o token foi gerado do lado do servidor ou do lado do cliente examinando o histórico de requisições do proxy.
Tokens vistos pela primeira vez do lado do cliente sugerem que a chave pode estar exposta ao código do lado do cliente, necessitando de investigação adicional.
Tokens originados do lado do servidor indicam um processo seguro.
Verifique se o token dura mais de 24h... talvez ele nunca expire. Se houver um campo "exp", verifique se o servidor está lidando com ele corretamente.
Defina o algoritmo usado como "Nenhum" e remova a parte da assinatura.
Use a extensão Burp chamada "JSON Web Token" para tentar essa vulnerabilidade e para mudar diferentes valores dentro do JWT (envie a requisição para Repeater e na aba "JSON Web Token" você pode modificar os valores do token. Você também pode selecionar para colocar o valor do campo "Alg" como "Nenhum").
O algoritmo HS256 usa a chave secreta para assinar e verificar cada mensagem. O algoritmo RS256 usa a chave privada para assinar a mensagem e usa a chave pública para autenticação.
Se você mudar o algoritmo de RS256 para HS256, o código do back end usa a chave pública como a chave secreta e então usa o algoritmo HS256 para verificar a assinatura.
Então, usando a chave pública e mudando RS256 para HS256, poderíamos criar uma assinatura válida. Você pode recuperar o certificado do servidor web executando isso:
Um atacante incorpora uma nova chave no cabeçalho do token e o servidor usa essa nova chave para verificar a assinatura (CVE-2018-0114).
Isso pode ser feito com a extensão "JSON Web Tokens" do Burp. (Envie a solicitação para o Repeater, dentro da aba JSON Web Token selecione "CVE-2018-0114" e envie a solicitação).
As instruções detalham um método para avaliar a segurança dos tokens JWT, particularmente aqueles que utilizam uma reivindicação de cabeçalho "jku". Essa reivindicação deve estar vinculada a um arquivo JWKS (JSON Web Key Set) que contém a chave pública necessária para a verificação do token.
Avaliação de Tokens com Cabeçalho "jku":
Verifique a URL da reivindicação "jku" para garantir que ela leva ao arquivo JWKS apropriado.
Modifique o valor "jku" do token para direcionar a um serviço web controlado, permitindo a observação do tráfego.
Monitoramento de Interação HTTP:
Observar solicitações HTTP para sua URL especificada indica as tentativas do servidor de buscar chaves do link fornecido.
Ao empregar jwt_tool
para esse processo, é crucial atualizar o arquivo jwtconf.ini
com sua localização pessoal do JWKS para facilitar os testes.
Comando para jwt_tool
:
Execute o seguinte comando para simular o cenário com jwt_tool
:
Uma reivindicação de cabeçalho opcional conhecida como kid
é utilizada para identificar uma chave específica, que se torna particularmente vital em ambientes onde múltiplas chaves existem para a verificação da assinatura do token. Essa reivindicação ajuda na seleção da chave apropriada para verificar a assinatura de um token.
Quando a reivindicação kid
está presente no cabeçalho, é aconselhável procurar no diretório da web pelo arquivo correspondente ou suas variações. Por exemplo, se "kid":"key/12345"
for especificado, os arquivos /key/12345 e /key/12345.pem devem ser procurados na raiz da web.
A reivindicação kid
também pode ser explorada para navegar pelo sistema de arquivos, potencialmente permitindo a seleção de um arquivo arbitrário. É viável testar a conectividade ou executar ataques de Server-Side Request Forgery (SSRF) alterando o valor de kid
para direcionar arquivos ou serviços específicos. Manipular o JWT para mudar o valor de kid
enquanto mantém a assinatura original pode ser alcançado usando a flag -T
no jwt_tool, como demonstrado abaixo:
Ao direcionar arquivos com conteúdo previsível, é possível forjar um JWT válido. Por exemplo, o arquivo /proc/sys/kernel/randomize_va_space
em sistemas Linux, conhecido por conter o valor 2, pode ser usado no parâmetro kid
com 2 como a senha simétrica para a geração do JWT.
Se o conteúdo da reivindicação kid
for utilizado para buscar uma senha em um banco de dados, uma injeção SQL pode ser facilitada modificando o payload kid
. Um exemplo de payload que usa injeção SQL para alterar o processo de assinatura do JWT inclui:
non-existent-index' UNION SELECT 'ATTACKER';-- -
Essa alteração força o uso de uma chave secreta conhecida, ATTACKER
, para a assinatura do JWT.
Um cenário onde o parâmetro kid
especifica um caminho de arquivo usado dentro de um contexto de execução de comando pode levar a vulnerabilidades de Execução Remota de Código (RCE). Ao injetar comandos no parâmetro kid
, é possível expor chaves privadas. Um exemplo de payload para alcançar RCE e exposição de chaves é:
/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&
jku significa JWK Set URL. Se o token usar uma reivindicação de cabeçalho “jku”, então verifique a URL fornecida. Isso deve apontar para uma URL contendo o arquivo JWKS que possui a Chave Pública para verificar o token. Modifique o token para apontar o valor jku para um serviço web que você possa monitorar o tráfego.
Primeiro, você precisa criar um novo certificado com novas chaves privadas e públicas.
Então você pode usar, por exemplo, jwt.io para criar o novo JWT com as chaves públicas e privadas criadas e apontando o parâmetro jku para o certificado criado. Para criar um certificado jku válido, você pode baixar o original e alterar os parâmetros necessários.
Você pode obter os parâmetros "e" e "n" de um certificado público usando:
URL X.509. Um URI apontando para um conjunto de certificados públicos X.509 (um padrão de formato de certificado) codificados em formato PEM. O primeiro certificado no conjunto deve ser aquele usado para assinar este JWT. Os certificados subsequentes assinam cada um o anterior, completando assim a cadeia de certificados. X.509 é definido na RFC 52807. A segurança de transporte é necessária para transferir os certificados.
Tente mudar este cabeçalho para uma URL sob seu controle e verifique se alguma solicitação é recebida. Nesse caso, você poderia adulterar o JWT.
Para forjar um novo token usando um certificado controlado por você, você precisa criar o certificado e extrair as chaves pública e privada:
Então você pode usar por exemplo jwt.io para criar o novo JWT com as chaves públicas e privadas criadas e apontando o parâmetro x5u para o certificado .crt criado.
Você também pode abusar de ambas essas vulnerabilidades para SSRFs.
Este parâmetro pode conter o certificado em base64:
Se o atacante gerar um certificado autoassinado e criar um token forjado usando a chave privada correspondente e substituir o valor do parâmetro "x5c" pelo certificado recém-gerado e modificar os outros parâmetros, nomeadamente n, e e x5t, então essencialmente o token forjado seria aceito pelo servidor.
Se o JWT tiver uma chave pública embutida como no seguinte cenário:
Usando o seguinte script nodejs, é possível gerar uma chave pública a partir desses dados:
É possível gerar uma nova chave privada/pública, embutir a nova chave pública dentro do token e usá-la para gerar uma nova assinatura:
Você pode obter o "n" e "e" usando este script nodejs:
Finalmente, usando a chave pública e privada e os novos valores "n" e "e", você pode usar jwt.io para forjar um novo JWT válido com qualquer informação.
Se algumas aplicações usam ES256 e utilizam o mesmo nonce para gerar dois jwts, a chave privada pode ser restaurada.
Aqui está um exemplo: ECDSA: Revelando a chave privada, se o mesmo nonce for usado (com SECP256k1)
A reivindicação JTI (JWT ID) fornece um identificador único para um Token JWT. Ele pode ser usado para evitar que o token seja reproduzido. No entanto, imagine uma situação em que o comprimento máximo do ID é 4 (0001-9999). As requisições 0001 e 10001 vão usar o mesmo ID. Portanto, se o backend estiver incrementando o ID em cada requisição, você poderia abusar disso para repetir uma requisição (precisando enviar 10000 requisições entre cada repetição bem-sucedida).
Ataques de Relay entre serviços
Foi observado que algumas aplicações web dependem de um serviço JWT confiável para a geração e gerenciamento de seus tokens. Foram registrados casos em que um token, gerado para um cliente pelo serviço JWT, foi aceito por outro cliente do mesmo serviço JWT. Se a emissão ou renovação de um JWT via um serviço de terceiros for observada, a possibilidade de se inscrever em uma conta em outro cliente desse serviço usando o mesmo nome de usuário/e-mail deve ser investigada. Em seguida, deve-se tentar reproduzir o token obtido em uma requisição para o alvo para ver se é aceito.
Um problema crítico pode ser indicado pela aceitação do seu token, potencialmente permitindo a falsificação da conta de qualquer usuário. No entanto, deve-se notar que a permissão para testes mais amplos pode ser necessária se inscrevendo em uma aplicação de terceiros, pois isso pode entrar em uma área cinza legal.
Verificação de Expiração de Tokens
A expiração do token é verificada usando a reivindicação "exp" Payload. Dado que os JWTs são frequentemente empregados sem informações de sessão, um manuseio cuidadoso é necessário. Em muitas instâncias, capturar e reproduzir o JWT de outro usuário poderia permitir a impersonificação desse usuário. O RFC do JWT recomenda mitigar ataques de repetição de JWT utilizando a reivindicação "exp" para definir um tempo de expiração para o token. Além disso, a implementação de verificações relevantes pela aplicação para garantir o processamento desse valor e a rejeição de tokens expirados é crucial. Se o token incluir uma reivindicação "exp" e os limites de tempo de teste permitirem, é aconselhável armazenar o token e reproduzi-lo após o tempo de expiração ter passado. O conteúdo do token, incluindo a análise de timestamp e verificação de expiração (timestamp em UTC), pode ser lido usando a flag -R da jwt_tool.
Um risco de segurança pode estar presente se a aplicação ainda validar o token, pois isso pode implicar que o token nunca poderia expirar.
Se você está interessado em carreira de hacking e hackear o inhackeável - estamos contratando! (fluência em polonês escrita e falada é necessária).
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)