¿Qué pasa si roban JWT?

201

Estoy tratando de implementar la autenticación sin estado con JWT para mis API RESTful.

AFAIK, JWT es básicamente una cadena encriptada pasada como encabezados HTTP durante una llamada REST.

Pero, ¿qué pasa si hay un espía que ve la solicitud y roba el token ? Entonces, ¿podrá falsificar una solicitud con mi identidad?

En realidad, esta preocupación se aplica a toda la autenticación basada en token .

¿Cómo prevenir eso? ¿Un canal seguro como HTTPS?

smwikipedia
fuente
1
Es por eso que los tokens a menudo solo son válidos por un corto período de tiempo. Y sí, debe usar HTTPS si le preocupa la confidencialidad de sus datos.
Jonathon Reinhart
44
@JonathonReinhart Pero si un token caduca pronto, mi cliente tendrá que obtener uno nuevo volviéndose a autenticar de vez en cuando. ¿No es un poco tedioso?
smwikipedia
@JonathonReinhart Creo que entiendo por qué el token es de corta duración. Porque de esa manera, el servidor no necesita realizar un seguimiento de la caducidad de un token y, por lo tanto, dar paso a la escalabilidad. Es una especie de trade-offentre having finer control of token expirationy having better scalability.
smwikipedia
2
¿Esto también puede ayudar? - "Un mecanismo de seguridad común para detectar el robo de tokens es realizar un seguimiento de los orígenes de la dirección IP de la solicitud". - descrito en detalle en la última sección aquí - firebase.google.com/docs/auth/admin/manage-sessions
Ula
3
Teóricamente, es imposible evitar el robo de fichas. Lo mejor que podemos hacer es detectar lo sucedido y luego revocar la sesión lo antes posible. El mejor método para la detección es usar tokens de actualización rotativos (como sugiere RFC 6819). Aquí hay un blog que explica esto en detalle: supertokens.io/blog/…
Rishabh Poddar

Respuestas:

284

Soy el autor de una biblioteca de nodos que maneja la autenticación con bastante profundidad, express-stormpath , por lo que intervendré con información aquí.

En primer lugar, los JWT generalmente NO están encriptados. Si bien hay una manera de cifrar los JWT (ver: JWE ), esto no es muy común en la práctica por muchas razones.

A continuación, cualquier forma de autenticación (usando JWT o no) está sujeta a ataques MitM (ataques intermedios). Estos ataques suceden cuando un atacante puede VER SU tráfico de RED a medida que realiza solicitudes a través de Internet. Esto es lo que su ISP puede ver, la NSA, etc.

Esto es contra lo que SSL ayuda a prevenir: al encriptar el tráfico de su RED desde su computadora -> algún servidor cuando se autentica, un tercero que está monitoreando el tráfico de su red NO puede ver sus tokens, contraseñas ni nada por el estilo a menos que de alguna manera puedan para obtener una copia de la clave SSL privada del servidor (poco probable). Esta es la razón por la que SSL es OBLIGATORIO para todas las formas de autenticación.

Digamos, sin embargo, que una persona es capaz de explotar su SSL y es capaz de ver su ficha: la respuesta a su pregunta es que , el atacante será capaz de utilizar esa señal para usted y solicitudes de maquillaje suplantar a su servidor.

Ahora, aquí es donde entran los protocolos.

Los JWT son solo un estándar para un token de autenticación. Se pueden usar para casi cualquier cosa. La razón por la cual los JWT son geniales es que puede incrustar información adicional en ellos, y puede validar que nadie se haya metido con eso (firma).

SIN EMBARGO, los JWT en sí mismos no tienen nada que ver con la 'seguridad'. Para todos los efectos, los JWT son más o menos lo mismo que las claves API: solo cadenas aleatorias que se utilizan para autenticarse en algún servidor.

Lo que hace que su pregunta sea más interesante es el protocolo que se está utilizando (probablemente OAuth2).

La forma en que funciona OAuth2 es que fue diseñado para dar a los clientes tokens TEMPORALES (¡como JWT!) Para autenticación solo durante un PERÍODO CORTO DE TIEMPO!

La idea es que si te roban el token, el atacante solo puede usarlo por un corto período de tiempo.

Con OAuth2, debe volver a autenticarse con el servidor de vez en cuando al proporcionar su nombre de usuario / contraseña O credenciales API y luego obtener un token a cambio.

Debido a que este proceso ocurre de vez en cuando, tus tokens cambian con frecuencia, lo que hace que sea más difícil para los atacantes hacerse pasar constantemente por ti sin pasar por grandes problemas.

Esperemos que esto ayude ^^

rdegges
fuente
3
El autor del siguiente artículo argumenta que una desventaja de JWT es que la única forma de recuperarse de un JWT robado es generar un nuevo par de claves y cerrar la sesión de manera efectiva para todos los usuarios. Mientras que con los identificadores de sesión almacenados en una base de datos, el sitio web podría eliminar solo las sesiones del usuario afectado y cerrar la sesión de todos los dispositivos. No estoy seguro de cómo OAuth2 encaja en la imagen aquí o si ayuda a mitigar las desventajas presentadas. medium.com/@rahulgolwalkar/…
Marcel
44
El autor es incorrecto. Existen diferentes patrones de diseño que puede usar para invalidar tokens. Pero en general: usar un JWT para cualquier tipo de propósito de autenticación es una mala idea. Es mucho más eficiente usar una cookie de sesión con una idea de sesión incrustada dentro que esté firmada criptográficamente.
rdegges
1
@rdegges, por favor, dime cómo JWT es una mala idea para la autenticación. ¿Y cómo puedo usar la cookie de sesión que mencionaste en tu comentario anterior?
noman tufail
66
Esto es demasiado largo para escribir una sola respuesta. Si desea obtener más información, he dado una charla detallada sobre el tema. Puedes ver mis diapositivas en línea: speakerdeck.com/rdegges/jwts-suck-and-are-stupid
rdegges
2
Teóricamente, es imposible evitar el robo de fichas. Lo mejor que podemos hacer es detectar lo sucedido y luego revocar la sesión lo antes posible. El mejor método para la detección es usar tokens de actualización rotativos (como sugiere RFC 6819). Aquí hay un blog que explica esto en detalle: supertokens.io/blog/…
Rishabh Poddar
31

Sé que esta es una vieja pregunta, pero creo que puedo dejar mis $ 0.50 aquí, probablemente alguien pueda mejorar o proporcionar un argumento para rechazar totalmente mi enfoque. Estoy usando JWT en una API RESTful sobre HTTPS (ofc).

Para que esto funcione, siempre debe emitir tokens de corta duración (depende de la mayoría de los casos, en mi aplicación en realidad configuro el expreclamo en 30 minutos y ttlen 3 días, por lo que puede actualizar este token siempre que ttlesté válido y el token no ha sido incluido en la lista negra )

Por lo tanto authentication service, para invalidar tokens, me gusta usar una capa de caché en memoria ( redis en mi caso) como JWT blacklist/ ban-listen frente, dependiendo de algunos criterios: (Sé que rompe la filosofía RESTful, pero los documentos almacenados son realmente efímero, ya que incluyo en la lista negra el tiempo restante de vida ( ttlreclamo)

Nota: los tokens en la lista negra no se pueden actualizar automáticamente

  • Si user.password o user.emailse ha actualizado (requiere confirmación de contraseña), el servicio de autenticación devuelve un token actualizado e invalida (lista negra) uno (s) anterior (es), por lo que si su cliente detecta que la identidad del usuario se ha visto comprometida de alguna manera, puede pedirle al usuario que cambie su contraseña . Si no desea utilizar la lista negra para ello, puede (pero no lo aliento) validar el iatreclamo (emitido en) contra el user.updated_atcampo (si jwt.iat < user.updated_atJWT no es válido).
  • El usuario ha cerrado sesión deliberadamente.

Finalmente, valida el token normalmente como todos lo hacen.

Nota 2: en lugar de usar el token en sí (que es realmente largo) como clave de la caché, sugiero generar y usar un token UUID para el jtireclamo. Lo cual es bueno y creo que (no estoy seguro ya que surgió en mi mente) también puede usar este mismo UUID que el token CSRF, devolviendo un secure/ non-http-onlycookie con él e implementando correctamente el X-XSRF-TOKENencabezado usando js. De esta manera, evita el trabajo informático de crear otro token para las comprobaciones CSRF.

Frondor
fuente
9
Nunca es demasiado tarde para aportar tu idea. Gracias por su respuesta.
smwikipedia
2
Si almacena una lista negra en el servidor que debe verificarse para cada solicitud, ¿por qué no usar simplemente una sesión antigua?
Franklin Yu
@FranklinYu Una lista negra es mucho más "barata" que una tienda de sesión completa. Dado que está almacenando objetos clave-valor de corta duración (dependiendo del tiempo de vida restante, que debería ser bastante corto), y eso sucede solo para las acciones de cierre de sesión y las acciones que invalidan los tokens, por lo que no todos los tokens son almacenado ofc.
Frondor
2
¿Qué tan barato puede ser? En primer lugar, si todavía está almacenando algo en el lado del servidor, no disfruta del beneficio de "escalabilidad" reclamado por JWT porque todavía hay un servidor central de listas negras con el que todo el servidor de aplicaciones necesita hablar antes de hacer nada. Si solo necesita almacenar una lista negra de 1k debido a un vencimiento rápido, puede hacer lo mismo para las sesiones y, por lo tanto, solo necesita almacenar sesiones de 1k.
Franklin Yu
3
Me gusta este enfoque. En realidad, no tiene que verificar la lista negra en cada solicitud, solo en una solicitud que ocurre después de que caduca el JWT (que puede leer desde el token) y hasta el período TTL posterior. En un caso de uso "estándar", eso debería suceder, como máximo, una vez en la vida de un token dado. Una vez actualizado, probablemente puede rechazar cualquier solicitud de actualización futura. Gracias @Frondor
John Ackerman
7

Lamento llegar un poco tarde en esto, pero tenía las mismas preocupaciones y ahora quiero contribuir con algo igual.

1) rdegges agregó un excelente punto, que JWT no tiene nada que ver con la "seguridad" y simplemente valida, si alguien se ha equivocado con la carga útil o no (firma); SSL ayuda a prevenir las infracciones.

2) Ahora, si ssl también se ve comprometido de alguna manera, cualquier espía puede robar nuestro token de portador (JWT) y suplantar al usuario genuino, un paso de siguiente nivel que se puede hacer es buscar la "prueba de posesión" de JWT del cliente .

3) Ahora, con este enfoque, el presentador del JWT posee una clave particular de prueba de posesión (POP), que el destinatario puede confirmar criptográficamente si la solicitud es del mismo usuario auténtico o no.

Remití Prueba de Posesión artículo para esto y estoy convencido con el apporach.

Estaré encantado, si puedo contribuir con algo.

Saludos (y)

yanky_cranky
fuente
0

¿No podemos simplemente agregar la ip del host inicial que ha solicitado generar este token JWT como parte del reclamo? Ahora, cuando el JWT es robado y utilizado desde una máquina diferente, cuando el servidor valida este token, podemos verificar si la IP de la máquina solicitada coincide con la establecida como parte del reclamo. Esto no coincidiría y, por lo tanto, el token puede ser rechazado. Además, si el usuario intenta manipular el token configurando su propia ip en el token, el token sería rechazado a medida que se modifica el token.

Venkatesh Vs
fuente
Esa es una solución posible, pero para los clientes detrás de un firewall es típico que una dirección IP se elija de un grupo de direcciones y eso puede cambiar en cualquier momento.
SpeedOfSpin