¿Es seguro almacenar un jwt en localStorage con reactjs?

147

Actualmente estoy construyendo una aplicación de página única usando reactjs. Leí que muchas de las razones para no usar localStorage se deben a las vulnerabilidades de XSS. Dado que React escapa de todas las entradas del usuario, ¿sería seguro usar localStorage?

Kaloyan Kosev
fuente
44
prefiera almacenamiento de sesión
Praneet Rohida
3
"Se recomienda no almacenar ninguna información confidencial en el almacenamiento local". -OWASP "almacenarlos en la memoria sin ninguna persistencia" -Auth0
avejidah 05 de
Creo que Auth0 podría haber cambiado su perspectiva sobre esto, porque no puedo encontrar la cita anterior en el enlace proporcionado
DauleDK

Respuestas:

141

En la mayoría de las aplicaciones modernas de una sola página, tenemos que almacenar el token en algún lugar del lado del cliente (caso de uso más común, para mantener al usuario conectado después de una actualización de la página).

Hay un total de 2 opciones disponibles: almacenamiento web (almacenamiento de sesión, almacenamiento local) y una cookie del lado del cliente. Ambas opciones son ampliamente utilizadas, pero esto no significa que sean muy seguras.

Tom Abbott resume bien la seguridad de la sesión JWT sessionStorage y localStorage :

Se puede acceder al almacenamiento web (localStorage / sessionStorage) a través de JavaScript en el mismo dominio. Esto significa que cualquier JavaScript que se ejecute en su sitio tendrá acceso al almacenamiento web, y debido a esto puede ser vulnerable a los ataques de scripting entre sitios (XSS) . En pocas palabras, XSS es un tipo de vulnerabilidad en la que un atacante puede inyectar JavaScript que se ejecutará en su página. Los ataques XSS básicos intentan inyectar JavaScript a través de entradas de formulario, donde el atacante pone <script>alert('You are Hacked');</script>un formulario para ver si lo ejecuta el navegador y si otros usuarios pueden verlo.

Para evitar XSS, la respuesta común es escapar y codificar todos los datos no confiables. ¡Reaccionar (principalmente) hace eso por ti! Aquí hay una gran discusión sobre la cantidad de protección contra vulnerabilidades XSS de la que es responsable React .

¡Pero eso no cubre todas las vulnerabilidades posibles! Otra amenaza potencial es el uso de JavaScript alojado en CDN o infraestructura externa .

Aquí está Tom nuevamente:

Las aplicaciones web modernas incluyen bibliotecas JavaScript de terceros para pruebas A / B, embudo / análisis de mercado y anuncios. Utilizamos administradores de paquetes como Bower para importar el código de otras personas en nuestras aplicaciones.

¿Qué sucede si solo uno de los scripts que usa está comprometido? JavaScript malicioso se puede incrustar en la página y el almacenamiento web se ve comprometido. Estos tipos de ataques XSS pueden obtener el almacenamiento web de todos los que visitan su sitio, sin su conocimiento. Esta es probablemente la razón por la cual un grupo de organizaciones aconseja no almacenar nada de valor ni confiar en ninguna información en el almacenamiento web. Esto incluye identificadores de sesión y tokens.

Por lo tanto, mi conclusión es que, como mecanismo de almacenamiento, el almacenamiento web no aplica ningún estándar seguro durante la transferencia . Quien lea el almacenamiento web y lo use debe hacer su debida diligencia para asegurarse de que siempre envíen el JWT a través de HTTPS y nunca HTTP.

Kaloyan Kosev
fuente
10
Entonces, si te entiendo correctamente, ¿me recomiendan las cookies? Solo por asegurar. ¡Gracias!
SuperLemon
77
Si. Recomiendo cookies debido a la seguridad adicional que brindan y la simplicidad de protección contra CSRF con marcos web modernos. El almacenamiento web (localStorage / sessionStorage) es vulnerable a XSS, tiene un área de superficie de ataque más grande y puede afectar a todos los usuarios de la aplicación en un ataque exitoso.
Kaloyan Kosev
48
Creo que tienes esto mezclado? Los marcos web modernos tienen fuertes defensas incorporadas para XSS. Pero no tanto por xsrf. La mejor defensa para xsrf es evitar el uso de cookies por completo. El almacenamiento local está encerrado en un dominio específico, lo que significa que un dominio de atacantes no puede acceder a él. Los marcos web se defienden contra xss al codificar y sanatizar automáticamente la entrada del usuario. Ver angular.io/guide/security
mikejones1477
47
Si "recomienda cookies [en su lugar]", ¿puedo recomendarle que diga eso en alguna parte de la respuesta? ¿En lugar de solo en los comentarios?
Spechter
77
Llegué un poco tarde, solo estoy leyendo estos temas ahora y estoy confundido acerca de una cosa, mucha gente habla de que estás protegido con una cookie http solo si estás comprimido con Xss, pero si tienes xss el atacante no necesita robarte nada, simplemente puede hacer una publicación desde la página para suplantarte usando esa cookie (incluso si no puede robarla). ¿¿¿Me estoy perdiendo de algo???
Borja Alvarez
35

Sé que esta es una vieja pregunta, pero de acuerdo con lo que dijo @ mikejones1477, las bibliotecas y los marcos de front-end modernos escapan del texto y le brindan protección contra XSS. La razón por la cual las cookies no son un método seguro usando credenciales es que las cookies no evitan CSRF cuando localStorage lo hace (también recuerde que JavaScript también puede acceder a las cookies, por lo que XSS no es el gran problema aquí), esta respuesta resume por qué .

El motivo por el que almacenar un token de autenticación en el almacenamiento local y agregarlo manualmente a cada solicitud protege contra CSRF es esa palabra clave: manual. Dado que el navegador no envía automáticamente ese token de autenticación, si visito evil.com y logra enviar una POST http://example.com/delete-my-account , no podrá enviar mi token de autenticación, así que La solicitud es ignorada.

Por supuesto, httpOnly es el santo grial, pero no puede acceder desde reactjs o cualquier marco js a su lado todavía tiene vulnerabilidad CSRF. Mi recomendación sería el almacenamiento local o, si desea utilizar cookies, asegúrese de implementar alguna solución a su problema CSRF como lo hace django .

Con respecto a los CDN, asegúrese de que no está utilizando algunos CDN extraños, por ejemplo, los CDN como google o bootstrap proporcionan, son mantenidos por la comunidad y no contienen código malicioso, si no está seguro, puede revisarlos.

Mauricio Cortazar
fuente
2
No estoy seguro de por qué diría que aún es vulnerable a CSRF mientras usa cookies. El uso de una cookie con las banderas HttpOnly SameSite=stricty securemantendrá segura la información que establezca en las cookies. Luego, contra XSS, simplemente asegúrese de que su JavaScript no esté al tanto de ningún dato relacionado con la autenticación, como tokens y contraseñas (es decir, no los almacene en el almacenamiento web): si importa un script malicioso, ese script no tendrá acceso a datos confidenciales. Sí, tampoco tendrá acceso al token a través de JS, pero eso realmente no debería ser un problema.
miphe
@miphe, eso es lo que dije. Pero el OP está pidiendo una forma de acceder desde javascript. Aquí solo estoy explicando cuál es la mejor manera de almacenar un token accesible desde js.
Mauricio Cortazar
21

Básicamente está bien almacenar su JWT en su almacenamiento local.

Y creo que esta es una buena manera. Si estamos hablando de XSS, XSS usando CDN, también es un riesgo potencial de obtener el inicio de sesión / pase de su cliente también. Almacenar datos en el almacenamiento local evitará al menos los ataques CSRF.

Debe ser consciente de ambos y elegir lo que quiere. No es necesario tener en cuenta ambos ataques, solo recuerde: SU APLICACIÓN COMPLETA ES SOLO SEGURA COMO EL PUNTO MENOS SEGURO DE SU APLICACIÓN.

Una vez más, el almacenamiento está bien, sea vulnerable a XSS, CSRF, ... no lo es

Alex Lyalka
fuente
2
Es por eso que es seguro hacer lo siguiente: - Almacene el JWT en una cookie para que no pueda recuperarse de XSS - Almacene un token CSRF en localStorage para que no pueda recuperarse de CSRF
Alejandro Cavazos
33
Sacas un buen punto: si tu sitio ejecuta un script malicioso, se acabó el juego de todos modos. Simplemente pueden vincular eventos keydown a entradas de tipo contraseña y robar la información de autenticación de su usuario de esa manera (que es mucho, mucho peor que robar un token de autenticación JWT). Almacenar JWT en localStorage hace poco para aumentar el daño ya inmenso posible de XSS.
Carl Leth
8

No es seguro si usa CDN:

JavaScript malicioso se puede incrustar en la página y el almacenamiento web se ve comprometido. Estos tipos de ataques XSS pueden obtener el almacenamiento web de todos los que visitan su sitio, sin su conocimiento. Esta es probablemente la razón por la cual un grupo de organizaciones aconseja no almacenar nada de valor ni confiar en ninguna información en el almacenamiento web. Esto incluye identificadores de sesión y tokens.

a través de la tormenta

Cualquier script que requiera desde el exterior podría verse comprometido y podría tomar cualquier JWTS del almacenamiento de su cliente y enviar datos personales al servidor del atacante.

Stephen L
fuente
66
Si no planeo usar cdns, ¿será seguro entonces?
1
El autor del artículo nunca hizo una distinción entre XSS en sitios servidos a través de un CDN o directamente desde un servidor central. ¿No se aplicaría su explicación aquí también en general, no solo para CDN?
Vlad
5

Localstorage está diseñado para ser accesible por javascript, por lo que no proporciona ninguna protección XSS. Como se mencionó en otras respuestas, hay muchas formas posibles de hacer un ataque XSS, desde el cual el almacenamiento local no está protegido de forma predeterminada.

Sin embargo, las cookies tienen banderas de seguridad que protegen de los ataques XSS y CSRF. El indicador HttpOnly evita que javascript del lado del cliente acceda a la cookie, el indicador Secure solo permite que el navegador transfiera la cookie a través de ssl, y el indicador SameSite asegura que la cookie se envíe solo al origen. Aunque acabo de comprobar y SameSite actualmente solo es compatible con Opera y Chrome, por lo tanto, para protegerse de CSRF es mejor usar otras estrategias. Por ejemplo, enviar un token encriptado en otra cookie con algunos datos públicos del usuario.

Por lo tanto, las cookies son una opción más segura para almacenar datos de autenticación.

Ivan
fuente
no puedo obtener: ¿cómo HttpOnly puede protegerlo de CSRF?
Alex Lyalka
@AlexLyalka No quise decir que HttpOnly previene de CSRF, en lugar de que todas las banderas de cookies juntas puedan proteger de XSS y CSRF. SameSite proporciona cierta protección, evitando que las cookies se envíen a un sitio diferente del origen. Aunque acabo de comprobar y el soporte para esa bandera es muy bajo. También es posible evitar CSRF con un token cifrado separado con alguna identificación de usuario, que se verifica en el servidor.
Ivan
1
Bueno, si alguien puede ejecutar código en su web, ¿no puede simplemente hacer una publicación en su web en nombre de su usuario? Ok, él no puede recibir sus cookies solo http, pero puede hacer llamadas usando esas cookies, así que todavía no puedo ver el punto
Borja Alvarez
2
@BorjaAlverez Hay una gran diferencia. Sí, a través de XSS alguien podría hacer solicitudes en nombre del usuario conectado, pero comprometer un token es peor. Por ejemplo: el token puede proporcionar acceso a las API que la aplicación cliente no usa; el token puede tener otra información sobre el usuario (dirección de correo electrónico, perfil y subvenciones); el token podría usarse en ataques de repetición contra su aplicación; el token se puede pasar como un id_token_hinta un servidor de autenticación OIDC; el token proporciona información de un atacante sobre el cifrado que se usó para firmarlo; etc.
avejidah
3

Una forma de ver esto es considerar el nivel de riesgo o daño.

¿Estás creando una aplicación sin usuarios, POC / MVP? ¿Eres una startup que necesita llegar al mercado y probar tu aplicación rápidamente? En caso afirmativo, probablemente solo implementaría la solución más simple y me mantendría enfocado en encontrar el producto adecuado para el mercado. Use localStorage ya que a menudo es más fácil de implementar.

¿Está creando una v2 de una aplicación con muchos usuarios activos diarios o una aplicación de la que las personas / empresas dependen en gran medida. ¿Ser pirateado significaría poco o ningún espacio para la recuperación? Si es así, analizaría detenidamente sus dependencias y consideraría almacenar información de token en una cookie solo http.

El uso de localStorage y el almacenamiento de cookies / sesiones tienen sus propios pros y contras.

Como se indica en la primera respuesta: si su aplicación tiene una vulnerabilidad XSS, ninguna protegerá a su usuario. Dado que la mayoría de las aplicaciones modernas tienen una docena o más de dependencias diferentes, se hace cada vez más difícil garantizar que una de las dependencias de su aplicación no sea vulnerable a XSS.

Si su aplicación tiene una vulnerabilidad XSS y un hacker ha podido explotarla, el hacker podrá realizar acciones en nombre de su usuario. El hacker puede realizar solicitudes GET / POST recuperando el token de localStorage o puede realizar solicitudes POST si el token se almacena en una cookie solo http.

El único inconveniente de almacenar su token en el almacenamiento local es que el hacker podrá leer su token.

HenokG
fuente
1

¿No son aceptables ni localStorage ni httpOnly cookies? En lo que respecta a una biblioteca de terceros comprometida, la única solución que conozco que reducirá / evitará el robo de información confidencial sería la Integridad de los recursos secundarios .

Subresource Integrity (SRI) es una característica de seguridad que permite a los navegadores verificar que los recursos que obtienen (por ejemplo, de un CDN) se entregan sin manipulación inesperada. Funciona al permitirle proporcionar un hash criptográfico que debe coincidir con un recurso obtenido.

Mientras la biblioteca de terceros comprometida esté activa en su sitio web, un keylogger puede comenzar a recopilar información como nombre de usuario, contraseña y cualquier otra cosa que ingrese en el sitio.

Una cookie httpOnly impedirá el acceso desde otra computadora, pero no hará nada para evitar que el hacker manipule la computadora del usuario.

SILENCIO
fuente
-10

Es seguro almacenar su token en localStorage siempre que lo cifre. A continuación se muestra un fragmento de código comprimido que muestra una de las muchas formas en que puede hacerlo.

    import SimpleCrypto from 'simple-crypto-js';

    const saveToken = (token = '') => {
          const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
          const encryptedToken = encryptInit.encrypt(token);

          localStorage.setItem('token', encryptedToken);
     }

Luego, antes de usar su token descifrarlo usando PRIVATE_KEY_STORED_IN_ENV_FILE

Kidali Kevin
fuente
@HassanAlthaf, te estás perdiendo el punto aquí, nunca habrá una aplicación de prueba 100% segura, es solo eso, estás reduciendo la superficie de ataque y al menos el archivo env no se publicará en github directamente. Además, el código incluido se ofuscará y destrozará, lo que dificultará que los atacantes los encuentren.
Kidali Kevin
No se supone que la clave privada esté expuesta. Ponerías en peligro toda la API.
Hassan Althaf
Según mi experiencia, si hiciste las cosas de forma inteligente y correcta, tu clave privada no estará expuesta en tu versión de producción, si es así, captura de pantalla para admitir esto o incluso una URL.
Kidali Kevin