
Script Python simples para verificar contra uma vulnerabilidade JWT hipotética.
Script python simples para verificar uma vulnerabilidade hipotética de JWT.
Digamos que existe uma aplicação que usa tokens JWT assinados com o algoritmo HS256. Um exemplo de token se parece com o seguinte:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.zbgd5BNF1cqQ_prCEqIvBTjSxMS8bDLnJAE_wE-0Cxg
O token acima pode ser decodificado para os seguintes dados:
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Para calcular a assinatura, o seguinte segredo é usado:
supersecret
O seguinte pseudocódigo é usado para calcular a assinatura:
$alg = "sha256";
$data = "...";
$key = "supersecret";
hmac($alg, $data, $key);
Mas e se o campo inesperado "kid":0 for injetado no cabeçalho?
{
"alg": "HS256",
"typ": "JWT",
"kid": 0
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
O campo kid é uma forma padrão de escolher uma chave. Minha suposição é que, se o campo kid não for esperado, pode haver uma implementação vulnerável que tratará o valor da string $key como um array:
hmac($alg, $data, $key[kid]);
Como resultado, o valor "s" ($key[0]) será usado como segredo HMAC.
O script injector.py pega o token JWT original, injeta o campo "kid":0 no cabeçalho e gera tokens assinados com segredos de uma letra (códigos ASCII: 32 - 126 [{espaço}, !, ", #, ..., x, y, z, {, |, }, ~]):
python3 injector.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.zbgd5BNF1cqQ_prCEqIvBTjSxMS8bDLnJAE_wE-0Cxg
Como resultado, dois arquivos são criados - tokens.txt e tokens_meta.txt. tokens.txt contém os tokens gerados e pode ser usado como uma lista de payloads para o Burp Intruder. Se algum token for válido (o que significa que a aplicação é vulnerável), o arquivo tokens_meta.txt pode ser usado para verificar qual algoritmo e segredo foram usados para gerar o token em questão. O arquivo tokens_meta.txt contém os seguintes dados:
token1:algorithm:secret
...
token{n}:algorithm:secret
Por favor, veja o CHANGELOG