Autenticación con JWT

3

Estoy construyendo SPA (React / Redux) y requiero la autenticación del usuario. He encontrado discusiones similares, pero no he encontrado respuestas para las preguntas que describo a continuación. Aquí hay algunas opciones que encontré para implementar:

Opción 1: mantener JWT en localStorage

Ataque CSRF : no es vulnerable, ya que no se utilizan cookies.

Ataque XSS : Vulnerable. Cualquier código JS en el front-end podrá robar el token y enviarlo al atacante. Con Content-Security-Policy habilitado, atacado no puede robarse / enviarse a sí mismo jwt, pero aún así puede realizar la solicitud directamente desde el navegador del cliente.

Opción 2: mantener JWT en la cookie ( secure y http-only )

Ataque CSRF : Vulnerable. El cliente puede seguir el sitio web malintencionado, lo que hará que la solicitud, la cookie adjunta y la solicitud sean exitosas

Ataque XSS : Vulnerable. JS no puede leer las cookies, pero a través de JS el atacante solo puede realizar solicitudes de back-end válido, las cookies se adjuntan automáticamente y todas las solicitudes se realizarán correctamente.

Opción 3: mantener JWT (con xsrf_token configurado) en cookie + mantener xsrf_token en localStorage / JS-legible cookie

La solución se basa en this y es similar a Método de envío doble de cookies

Ataque CSRF : No es vulnerable. Si el cliente sigue un sitio web malintencionado, que realiza una solicitud astuta, esa solicitud se descartará, ya que xsrf_token no se pasó del navegador del cliente junto con la cookie. Y, dado que la cookie no es visible para el atacante (viene directamente del navegador del cliente), no puede crear un xsrf_token falso para adjuntar con la solicitud.

Ataque XSS : Vulnerable. Los atacantes JS pueden leer xsrf_token en localStorage / JS-cookie legible. Por lo tanto, un atacante podrá realizar una solicitud maliciosa directamente desde su JS inyectado desde el navegador del cliente.

Originalmente, quería usar la opción 1. Pero me preocupaba XSS, así que comencé a buscar alternativas. Este artículo y el número de otros desaconseja el almacenamiento local, y recomienda el uso de la protección CSRF de Cookie +.

La opción 3 parece ser la solución popular, a partir de los datos recopilados, pero aún tiene XSS, al igual que la opción 1: JS inyectado puede realizar solicitudes maliciosas directamente desde el navegador del cliente. El único beneficio es que, en la opción 1, el usuario / atacante puede leer los datos codificados en JWT, mientras que en la opción 3 no lo está (como se almacena en una cookie). pregunta relacionada

Q1. ¿Hay otros beneficios de la Opción 3 sobre la Opción 1?

Q2. Si opto por la opción 3, ¿estoy introduciendo algunos otros vectores de ataque que aún no he considerado?

Q3. ¿Hay alguna otra forma de mitigación de CSRF, en lugar de mantener el estado en el front-end (localStorage / sessionStorage / Redux store / JS-legible cookie) que siempre es vulnerable a XSS?

Sé que no hay una bala mágica en seguridad. ¿Pero quizás hay otros enfoques / opciones para este problema? Para eliminar XSS, debe ir al modo de cookie completo. Pero para ir solo a las cookies, debe tener xsrf_token de todos modos en el front-end del usuario (localStorage / sessionStorage / Redux store / JS-legible cookie), que es vulnerable a XSS. Esto parece ser un problema catch-22.

    
pregunta Ilya 15.05.2018 - 08:11
fuente

1 respuesta

2

Comencemos con la parte fácil: la opción # 2 no es una opción. Viene sin protección CSRF, por lo que es inherentemente vulnerable. En realidad, la opción # 3 es prácticamente la opción # 2 con CSRF-protection en la parte superior. Por lo tanto, tiene razón al centrar su pregunta en la elección entre # 1 y # 3.

  

¿Hay otros beneficios de la Opción 3 sobre la Opción 1?

En realidad no. Y no estoy seguro de que el beneficio que mencionas (ser capaz de proteger el JWT con la bandera de solo HTTP) sea un beneficio tan grande.

Ser capaz de robar el JWT es conveniente para el atacante, ya que puede hacer lo que quiera hacer desde su propia computadora. Pero dada la vulnerabilidad de XSS, cualquier cosa que pueda hacer en su propia computadora con el JWT también puede hacerlo desde la computadora de las víctimas usando scripts inyectados. Eso podría ser un poco más molesto para el atacante, pero no detendría a un adversario determinado.

Así que al final, creo que la elección entre el número 1 y el número 3 es principalmente una preferencia personal. Personalmente me gusta el # 1 mejor, porque lo encuentro más limpio y más directo. Además, se ocupa de la situación de CSRF de forma ordenada, sin que tenga que mover un dedo.

  

Si voy con la Opción 3, ¿estoy introduciendo algunos otros vectores de ataque que aún no he considerado?

Tal vez.

En general, una debilidad con el patrón de doble envío de cookies es que permite ataques de subdominio . Esto es algo mitigado por el uso de un JWT. Dado que está firmado, un dominio de hermanos no pudo volver a escribir esa cookie. Pero (al menos en algunos navegadores) un subdominio podría leerlo y, por lo tanto, realizar un ataque CSRF. El uso de un encabezado HTTP en lugar de un campo de formulario para el envío doble haría que este ataque sea mucho más difícil, si no imposible (salvo algo como un exploit de Flash).

Tenga en cuenta que la seguridad de esta opción depende completamente de que obtenga la protección CSRF correcta.

  

¿Existe alguna otra forma de mitigación de CSRF, en lugar de mantener el estado en el front-end (localStorage / sessionStorage / Redux store / JS-legible cookie) que siempre es vulnerable a XSS?

No. Si eres vulnerable a XSS, todas las protecciones CSRF desaparecen por la ventana. Y realmente no importa. Porque si puedo hacer XSS, ya no necesito CSRF. Por lo tanto, tratar de encontrar una manera de protegerse de CSRF en caso de XSS no solo es imposible, sino que también es inútil.

Cada minuto que dedica a pensar en cómo proteger su token CSRF en caso de un ataque XSS es un minuto que debería haber intentado detener los ataques XSS.

    
respondido por el Anders 15.05.2018 - 13:20
fuente

Lea otras preguntas en las etiquetas