
Prueba de concepto para CVE-2025-65945 (Verificación inadecuada de la firma criptográfica en node-jws)
Esto es una prueba de concepto para un bypass de verificación de firma en la librería node-jws. El error permite a atacantes falsificar JWTs válidos cuando el servidor deriva secretos HMAC de datos controlados por el usuario.
La función jws.createVerify() no valida que se haya proporcionado un secreto cuando se usan algoritmos HMAC. Si tu aplicación busca secretos basándose en algo del JWT (como un encabezado kid) y esa búsqueda falla, podrías terminar verificando con un secreto vacío.
Un atacante puede explotar esto:
undefined, que se convierte a cadena vacíaEl atacante puede ahora suplantar a cualquier persona o concederse privilegios de administrador.
Actualiza a 3.2.3+ o 4.0.1+ para solucionarlo.
Asegúrate de tener Bun instalado, luego:
# Instalar la versión vulnerable
bun install [email protected]
# Ejecutar el exploit
bun run exploit.js
Deberías ver una salida que muestra un token de administrador falsificado siendo aceptado como válido.
El PoC simula un servidor que:
kid (ID de clave) del JWTcreateVerify() con la API de streamingEl atacante crea un JWT con kid: "non-existent-key" y lo firma con un secreto vacío. Cuando el servidor intenta buscar esta clave, obtiene undefined, escribe una cadena vacía en el flujo de verificación, y el token falsificado pasa la validación.
# Actualizar a la versión parcheada
bun install [email protected]
# Ejecutar de nuevo – debería fallar ahora
bun run exploit.js
Con la versión parcheada, verás un error: secret must be a string or buffer or a KeyObject. La corrección valida que las operaciones HMAC tengan un secreto adecuado antes de proceder.
Si tu código se parece a esto, podrías estar afectado:
const decoded = jws.decode(token);
const secret = lookupSecret(decoded.header.kid); // podría devolver undefined!
const verifier = jws.createVerify({
algorithm: "HS256",
signature: token,
});
verifier.secret.write(secret); // ups
verifier.secret.end();