Dividir un JWT entre carga útil y firma
Contexto: Estoy buscando soluciones de almacenamiento para tokens JWT en una aplicación de una sola página.
- Almacenar el JWT en el almacenamiento local no es seguro y es propenso a ataques XSS.
- Almacenar el JWT en una cookie segura / solo HTTP es más seguro, pero propenso a ataques CSRF.
Estoy estudiando el siguiente escenario:
Tras la autenticación, un token de actualización se almacena en una cookie segura solo http. Solo se puede usar para obtener un token de acceso.
Tras la autorización, el backend responde con un token de acceso JWT. El encabezado y la parte de carga útil del JWT están dentro del cuerpo de la respuesta. La firma del token no se envía y se establece en una cookie segura solo http (estricta del mismo sitio si es posible, pero supongamos que no es el caso). El encabezado + carga útil se almacena en la memoria.
El JWT contiene las siguientes afirmaciones
- iat, nbf, exp (OMI adivinable)
- afirmaciones relativas a la identidad y los permisos del usuario (se puede adivinar si se conoce la identidad del usuario)
- jti, que contiene un número aleatorio criptográficamente seguro (en mi caso generado con secretos de Python )
Al realizar solicitudes, el SPA envía el encabezado + carga útil a través de XHR / fetch en un encabezado de autorización. La firma se envía junto con las cookies. El backend concatena ambos y verifica la firma.
- ¿Es este mecanismo seguro contra ataques CSRF? ¿Las afirmaciones de jti hacen que el token de autorización + la cookie de firma sea una técnica de mitigación de CSRF válida?
- ¿Es este mecanismo más seguro contra ataques XSS que almacenar el JWT dentro del almacenamiento local? (¿Podría un ataque que usa XSS también robar fácilmente la firma, como con un exploit TRACE )?
Nota: He leído esta pregunta que es similar, pero demasiado amplia, así que la estoy publicando para obtener una respuesta más precisa.
Respuestas
¿Es este mecanismo seguro contra ataques CSRF?
Este método de dividir un JWT y almacenar la firma en la cookie y el resto del token en el almacenamiento del navegador no proporciona ninguna protección adicional contra los ataques CSRF que si todo el JWT se almacenara en el almacenamiento local o de sesión. Sí, mitigará los ataques CSRF, pero no necesita agregar la sobrecarga innecesaria de dividir y concatenar JWT en el servidor. Almacenar JWT en almacenamiento local y aceptarlos solo en los encabezados de autorización es suficiente para proteger su aplicación de los ataques CSRF.
¿Es este mecanismo más seguro contra ataques XSS que almacenar el JWT dentro del almacenamiento local? (¿Podría un ataque que usa XSS también robar fácilmente la firma, como con un exploit TRACE)?
Si su enfoque está únicamente en que un atacante pueda robar JWT, este enfoque es seguro a menos que, como mencionó correctamente, TRACE esté habilitado en el servidor.
Sin embargo, esto no hace que su aplicación sea más segura de los ataques XSS. Por ejemplo, si puedo ejecutar Javascript arbitrario en su aplicación, puedo obtener el encabezado JWT + la carga útil del Almacenamiento local y simplemente enviar un XHR a un punto final sensible manteniendo con Credenciales establecido en Verdadero. Este punto final podría diseñarse cambiando la dirección de correo electrónico de la cuenta, por ejemplo. Eso inmediatamente conduce a una toma de control de la cuenta. No es necesario robar cookies ni JWT.
Resumiendo: este enfoque proporciona cierta protección contra los tokens de sesión al separar la firma del resto del token. Sin embargo, cuando se trata de XSS, robar tokens de sesión no es el único riesgo que debería tener en cuenta.