¿Dónde almacenar JWT en el navegador? ¿Cómo protegerse contra CSRF?

159

Sé la autenticación basada en cookies. El indicador SSL y HttpOnly se puede aplicar para proteger la autenticación basada en cookies de MITM y XSS. Sin embargo, se necesitarán medidas más especiales para aplicar con el fin de protegerlo de CSRF. Son solo un poco complicados. ( referencia )

Recientemente, descubrí que JSON Web Token (JWT) es bastante popular como una solución para la autenticación. Sé todo sobre codificar, decodificar y verificar JWT. Sin embargo, no entiendo por qué algunos sitios web / tutoriales dicen que no se necesita protección CSRF si se usa JWT. He leído bastante e intento resumir los problemas a continuación. Solo quiero que alguien pueda proporcionar el panorama general de JWT y aclarar los conceptos que no entendí sobre JWT.

  1. Si el JWT se almacena en una cookie, creo que es lo mismo que la autenticación basada en cookies, excepto que el servidor no necesita tener sesiones para verificar la cookie / token. Todavía existe el riesgo de CSRF si no se implementa ninguna medida especial. ¿No se almacena JWT en una cookie?

  2. Si el JWT se almacena en localStorage / sessionStorage, entonces no hay cookies, por lo que no es necesario protegerse contra CRSF. La pregunta es cómo enviar el JWT al servidor. Encontré aquí sugiere usar jQuery para enviar el JWT por encabezado HTTP de solicitudes ajax. Entonces, ¿solo las solicitudes ajax pueden hacer la autenticación?

  3. Además, encontré un programa de blog más para usar "Encabezado de autorización" y "Portador" para enviar el JWT. No entiendo el método del que habla el blog. ¿Podría alguien explicarme más sobre "Encabezado de autorización" y "Portador"? ¿Esto hace que el JWT se transmita por el encabezado HTTP de TODAS las solicitudes? En caso afirmativo, ¿qué tal CSRF?

Timespace7
fuente

Respuestas:

70

Los tokens JWT son populares ya que se usan como el formato de token predeterminado en los nuevos protocolos de autorización y autenticación como OAuth 2.0 y OpenID Connect .

Cuando el token se almacena en una cookie, el navegador lo enviará automáticamente junto con cada solicitud al mismo dominio y esto sigue siendo vulnerable a los ataques CSRF.

La autenticación de portador es uno de los esquemas de autenticación definidos en HTTP. Básicamente significa que YOUpegue el token (JWT) en el encabezado HTTP de autorización de una solicitud. El navegador lo NOThará automáticamente, por lo que no es adecuado para proteger su sitio web. Como el navegador no agrega automáticamente el encabezado a su solicitud, no es vulnerable a un ataque CSRF, que depende de que su información de autenticación se envíe automáticamente al dominio original.

El esquema de portador se usa a menudo para proteger las API web (servicios REST) ​​que se consumen a través de llamadas AJAX o desde clientes móviles.

MvdD
fuente
1
@ Timespace7 No, los tokens JWT también se usan a menudo desde clientes nativos. OAuth 2.0 tiene flujos dirigidos específicamente a clientes nativos (móviles). Lo que no hacen es la autenticación implícita del navegador (como cookies o autenticación básica).
MvdD
55
Estoy diciendo que si su API solo recupera el token JWT del encabezado de autorización, no es vulnerable a CSRF. Cualquier sitio o API que obtenga el token de una cookie necesita mitigación CSRF.
MvdD
13
¿Esto significa que podemos almacenar efectivamente el jwt en una cookie y será seguro si enviamos solicitudes con él en el encabezado de Autorización?
cameronroe
10
@cameronjroe puede almacenarlo en sus cookies, pero solo si no usa sus cookies para la autenticación (en este caso, usa sus encabezados)
Jaakko
1
Las llamadas AJAX también se originan desde el navegador. Los tokens JWT se utilizan principalmente para autenticar las API web (datos de publicación) frente a las cookies utilizadas para autenticar las aplicaciones web (marcado de publicación, imágenes, CSS y JavaScript)
MvdD
144

Necesitamos almacenar el JWT en la computadora del cliente. Si lo almacenamos en un LocalStorage / SessionStorage, entonces puede ser fácilmente capturado por un ataque XSS. Si lo almacenamos en cookies, un pirata informático puede usarlo (sin leerlo) en un ataque CSRF y suplantar al usuario y ponerse en contacto con nuestra API y enviar solicitudes para realizar acciones u obtener información en nombre de un usuario.

Pero hay varias formas de asegurar el JWT en las cookies para que no se roben fácilmente (pero todavía hay algunas técnicas avanzadas para robarlas). Pero si desea confiar en LocalStorage / SessionStorage, puede acceder a él mediante un simple ataque XSS.

Entonces, para resolver el problema CSRF, utilizo cookies de envío doble en mi aplicación.

Método de doble envío de cookies

  1. Almacene JWT en una cookie HttpOnly y úsela en modo seguro para transferir a través de HTTPS.

  2. La mayoría de los ataques CSRF tienen un origen o encabezado de referencia diferente con su host original en sus solicitudes. Así que verifique si tiene alguno de ellos en el encabezado, ¿provienen de su dominio o no? Si no, rechazarlos. Si tanto el origen como el referente no están disponibles en la solicitud, no se preocupe. Puede confiar en el resultado de los resultados de validación del encabezado X-XSRF-TOKEN que explico en el siguiente paso.

  3. Si bien el navegador proporcionará automáticamente sus cookies para el dominio de la solicitud, existe una limitación útil: el código JavaScript que se ejecuta en un sitio web no puede leer las cookies de otros sitios web. Podemos aprovechar esto para crear nuestra solución CSRF. Para evitar ataques CSRF, debemos crear una cookie extra legible de Javascript que se llama: XSRF-TOKEN. Esta cookie debe crearse cuando el usuario inicia sesión y debe contener una cadena aleatoria, no adivinable. También guardamos este número en el JWT como un reclamo privado. Cada vez que la aplicación JavaScript desee realizar una solicitud, deberá leer este token y enviarlo en un encabezado HTTP personalizado. Debido a que estas operaciones (leer la cookie, configurar el encabezado) solo se pueden realizar en el mismo dominio de la aplicación JavaScript,

Angular JS te hace la vida más fácil

Afortunadamente, estoy usando Angular JS en nuestra plataforma y paquetes de Angular con el enfoque de token CSRF, lo que simplifica la implementación. Por cada solicitud que nuestra aplicación Angular haga del servidor, el $httpservicio Angular hará estas cosas automáticamente:

  • Busque una cookie llamada XSRF-TOKEN en el dominio actual.
  • Si se encuentra esa cookie, lee el valor y lo agrega a la solicitud como el encabezado X-XSRF-TOKEN.

Por lo tanto, la implementación del lado del cliente se gestiona automáticamente. Solo necesitamos establecer una cookie nombrada XSRF-TOKENen el dominio actual en el lado del servidor y cuando nuestra API recibió alguna llamada del cliente, debe verificar el X-XSRF-TOKENencabezado y compararlo con el XSRF-TOKENen el JWT. Si coinciden, entonces el usuario es real. De lo contrario, es una solicitud falsificada y puede ignorarla. Este método está inspirado en el método de "Cookie de doble envío".

Precaución

En realidad, aún eres susceptible a XSS, es solo que el atacante no puede robarte el token JWT para su uso posterior, pero aún puede hacer solicitudes en nombre de tus usuarios usando XSS.

Ya sea que almacene su JWT en localStorageo almacene su token XSRF en una cookie que no sea HttpOnly, XSS puede agarrarlos fácilmente. Incluso su JWT en una cookie HttpOnly puede ser capturado por un ataque XSS avanzado como el método XST .

Por lo tanto, además del método de doble envío de cookies, siempre debe seguir las mejores prácticas contra XSS, incluido el escape de contenido. Esto significa eliminar cualquier código ejecutable que haga que el navegador haga algo que usted no quiere que haga. Por lo general, esto significa eliminar // <![CDATA[etiquetas y atributos HTML que hacen que se evalúe JavaScript.

Leer más aquí:

Iman Sedighi
fuente
1
@AranDehkharghani sí, supongo que evita el ataque de repetición, especialmente si cambia JWT y caduca el JWT anterior cada vez que lo utiliza API. significa que su JWT se convertirá en una contraseña de un solo uso (OTP). Puede usar JWT de diferentes maneras dependiendo de cuánto le importe la seguridad en su plataforma.
Iman Sedighi
77
Como mencionó, si un sitio web es vulnerable a XSS, entonces es solo cuestión de tiempo antes de que el usuario sea explotado. Parece que estamos cambiando una complejidad significativa por un aumento muy pequeño en la seguridad.
shusson
3
@shusson Debes ocuparte de los ataques XSS y XSRF para proteger tu JWT. No estoy de acuerdo con que esté intercambiando una complejidad significativa por un aumento muy pequeño en la seguridad. Si la seguridad es importante, debe hacer todo lo posible para no tener vulnerabilidades XSS. Este método está diseñado para proteger su token de los ataques XSRF. pero no significa que pueda ignorar las vulnerabilidades de XSS.
Iman Sedighi
55
@ImanSedighi No estaba claro, al almacenar el jwt en una cookie está agregando complejidad y ahora tiene que protegerse contra XSRF. Entonces, ¿por qué no usar el almacenamiento local con tokens de corta vida y concentrarse en prevenir XSS?
shusson
2
@Royi Namir: ¡Spoofing by Wireshark no debería ser una preocupación si usa un certificado SSL de $ 10! Si la seguridad del sitio web es importante, debe cifrar los datos y utilizar el protocolo HTTPS.
Iman Sedighi
2

Otro ángulo para todo el problema del almacenamiento de JWT:

  1. Los JWT nunca deben almacenarse en su almacenamiento local
  2. De hecho, ni siquiera deberían almacenarse en sus cookies , a menos que pueda implementar una protección CSRF muy estricta

Mira esto para motivarte

  • JWT como id_token es como sus credenciales de usuario
  • JWT como acceso_token es como su token de sesión

La opción más segura es en la memoria . Mira esto para una inmersión profunda

humano
fuente