¿Token CSRF necesario cuando se usa la autenticación sin estado (= sin sesión)?

125

¿Es necesario usar Protección CSRF cuando la aplicación se basa en autenticación sin estado (usando algo como HMAC)?

Ejemplo:

  • Tenemos una sola aplicación página (de lo contrario tenemos que añadir el token en cada enlace: <a href="...?token=xyz">...</a>.

  • El usuario se autentica usando POST /auth. En la autenticación exitosa, el servidor devolverá algunos tokens.

  • El token se almacenará a través de JavaScript en alguna variable dentro de la aplicación de página única.

  • Este token se usará para acceder a URL restringidas como /admin.

  • El token siempre se transmitirá dentro de los encabezados HTTP.

  • No hay sesión HTTP y NO cookies.

Por lo que entiendo, no debería haber (?!) posibilidad de usar ataques entre sitios, porque el navegador no almacenará el token y, por lo tanto, no puede enviarlo automáticamente al servidor (eso es lo que sucedería al usar Cookies / Sesión).

¿Me estoy perdiendo de algo?

Benjamin M
fuente
66
Tenga cuidado con la autenticación básica. Muchos navegadores enviarán automáticamente los encabezados de autenticación básicos para el resto de la sesión. Esto puede hacer que la autenticación básica sea tan vulnerable a CSRF como la autenticación de cookies.
phylae

Respuestas:

159

Encontré información sobre CSRF + sin utilizar cookies para la autenticación:

  1. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
    "ya que no depende de las cookies, no necesita protegerse contra las solicitudes de sitios cruzados"

  2. http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
    "Si pasamos por las cookies, realmente necesita hacer CSRF para evitar solicitudes de sitios cruzados. Eso es algo que podemos olvídalo cuando uses JWT como verás ".
    (JWT = Json Web Token, una autenticación basada en token para aplicaciones sin estado)

  3. http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
    "La forma más fácil de realizar la autenticación sin arriesgar vulnerabilidades CSRF es simplemente evitar el uso de cookies para identificar al usuario "

  4. http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
    "El mayor problema con CSRF es que las cookies no proporcionan absolutamente ninguna defensa contra este tipo de ataque. Si está utilizando la autenticación de cookies también debe emplear medidas adicionales para protegerse contra el CSRF. La precaución más básica que puede tomar es asegurarse de que su aplicación nunca realice ningún efecto secundario en respuesta a las solicitudes GET ".

Hay muchas más páginas, que indican que no necesita ninguna protección CSRF, si no utiliza cookies para la autenticación. Por supuesto, aún puede usar cookies para todo lo demás, pero evite almacenar algo como session_iddentro.


Si necesita recordar al usuario, hay 2 opciones:

  1. localStorage: Un almacén de valores clave en el navegador. Los datos almacenados estarán disponibles incluso después de que el usuario cierre la ventana del navegador. Otros sitios web no pueden acceder a los datos porque cada sitio tiene su propio almacenamiento.

  2. sessionStorage: También un almacén de datos en el navegador. La diferencia es: los datos se eliminan cuando el usuario cierra la ventana del navegador. Pero sigue siendo útil, si su aplicación web consta de varias páginas. Entonces puedes hacer lo siguiente:

    • El usuario inicia sesión y luego almacena el token sessionStorage
    • El usuario hace clic en un enlace, que carga una nueva página (= un enlace real y no reemplaza el contenido de JavaScript)
    • Todavía puedes acceder al token desde sessionStorage
    • Para cerrar sesión, puede eliminar manualmente el token sessionStorageo esperar a que el usuario cierre la ventana del navegador, lo que borrará todos los datos almacenados.

(para que ambos echen un vistazo aquí: http://www.w3schools.com/html/html5_webstorage.asp )


¿Existen estándares oficiales para la autenticación de token?

JWT (Json Web Token): Creo que todavía es un borrador, pero muchas personas ya lo utilizan y el concepto parece simple y seguro. (IETF: http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25 )
También hay bibliotecas para muchos marcos disponibles. ¡Solo busca en Google!

Benjamin M
fuente
37
Gran resumen sobre CSRF! Notaré que almacenar sus tokens en localStorage o sessionStorage es vulnerable a ataques XSS y que los datos se pueden ver mediante scripts en la página, por lo que si tiene un script comprometido servido desde un CDN o si hay código malicioso en uno de sus Las bibliotecas JS pueden robar el token de esos lugares de almacenamiento. Consulte: stormpath.com/blog/ ... Creo que el enfoque más seguro es almacenar un token JWT + CSRF en la cookie y luego colocar su JWT calculado con el token CSRF dentro del encabezado de la solicitud.
Aaron Gray
En cuanto a: "La precaución más básica que puede tomar es asegurarse de que su aplicación nunca realice ningún efecto secundario en respuesta a las solicitudes GET". ¿Es posible que un ataque CSRF falsifique una solicitud POST?
Costa
Dependiendo de la aplicación del lado del servidor, PUEDE ser posible. Hay marcos web, que usan algo como http://.../someRestResource?method=POST. Por lo tanto, es básicamente una GETsolicitud, pero la aplicación del servidor la interpreta como una POSTsolicitud, porque se configuró para usar el methodparámetro en lugar del encabezado HTTP. ...Con respecto a los navegadores web comunes, hacen cumplir la Política del mismo origen y solo ejecutarán GETsolicitudes a servidores extranjeros. Aunque podría ser posible ejecutar POSTsolicitudes si el navegador web no aplica esos estándares web (error, malware).
Benjamin M
1
Además de Server Side App: Todavía no es posible enviar un Cuerpo de solicitud, porque los navegadores comunes no lo permitirán. Sin embargo, si la aplicación del servidor lo permite method=POST, también podría body={someJson}anular el cuerpo de solicitud predeterminado. Ese es un diseño de API realmente malo y extremadamente arriesgado. Sin embargo, si su aplicación de servidor lo permite http://...?method=POST&body={someJson}, debería pensar demasiado sobre lo que hizo allí y por qué y si es necesario. (Yo diría que en el 99,9999% de los casos es que no es necesario). Además, los navegadores solo pueden enviar unos pocos kilobytes de esta manera.
Benjamin M
@BenjaminM notó que la Política del mismo origen solo impide que el código javaScript acceda al resultado, de modo que mientras la solicitud está "bloqueada", en realidad llega al servidor: jsbin.com/mewaxikuqo/edit?html,js,output Solo probé esto en Firefox, pero puede abrir las herramientas de desarrollo y ver que incluso si obtiene una "Solicitud de origen cruzado bloqueada", el servidor remoto realmente ve la solicitud completa. Es por eso que debe tener tokens o encabezados personalizados (y, si es posible, ambos) para todas sus solicitudes POST
Yoni Jah
59

TL; DR

Un JWT, si se usa sin Cookies, niega la necesidad de un token CSRF, ¡PERO! almacenando JWT en session / localStorage, expone su JWT y la identidad del usuario si su sitio tiene una vulnerabilidad XSS (bastante común). Es mejor añadir una csrfTokenclave para la JWT y almacenar la JWT en una cookie con securey http-onlyconjunto de atributos.

Lea este artículo con una buena descripción para obtener más información https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

Puede hacer que esta protección CSRF sea apátrida al incluir un reclamo xsrfToken JWT:

{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }

Por lo tanto, deberá almacenar el csrfToken en localStorage / sessionStorage, así como en el propio JWT (que se almacena en una cookie segura y solo http). Luego, para la protección csrf, verifique que el token csrf en el JWT coincida con el encabezado csrf-token enviado.

Scott Jungwirth
fuente
2
¿Se debe eximir el uso del token csrf durante la autenticación API del usuario?
user805981
3
Vale la pena señalar (como otros también han mencionado en los comentarios en el enlace de origen) que cualquier mitigación de CSRF que use a) cookies, que no son http-only ob) almacena el token CSRF en el almacenamiento local es vulnerable a XSS. Esto significa que el enfoque presentado puede ayudar a mantener el JWT en secreto de un atacante que usa XSS, pero un atacante aún podría ejecutar una solicitud maliciosa en su API porque puede proporcionar un JWT válido (a través de la cookie, gracias navegador) y token CSRF (leído mediante JS inyectado desde el almacenamiento local / cookie).
Johannes Rudolph
1
En realidad, incluso un token CSRF no puede protegerlo a este nivel de XSS, ya que está asumiendo que el atacante puede acceder a localStorage, que la única forma de acceder actualmente es tener acceso a nivel de script, que de todos modos puede echar un vistazo al token CSRF .
válido el
1
¿No es eso lo que dijo @JohannesRudolph? Tan pronto como almacene el token CSRF en el almacenamiento web / cookie no solo http, aumentará su huella de un ataque XSS porque se puede acceder a través de JS.
adam-beck
1
No soy un experto total aquí, pero si todavía está expuesto a XSS como lo estaba al principio, no estoy seguro de qué parte es mejor agregar ... realmente se mantiene. Probablemente sea un poco (?) Más complicado para un atacante obtener el token CSRF, pero al final todavía puede realizar una solicitud en su nombre, incluso sin saber realmente el token JWT. ¿Es eso correcto? Gracias
superjos