¿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?
Respuestas:
Encontré información sobre CSRF + sin utilizar cookies para la autenticación:
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"
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)
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 "
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_id
dentro.Si necesita recordar al usuario, hay 2 opciones:
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.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:sessionStorage
sessionStorage
sessionStorage
o 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!
fuente
http://.../someRestResource?method=POST
. Por lo tanto, es básicamente unaGET
solicitud, pero la aplicación del servidor la interpreta como unaPOST
solicitud, porque se configuró para usar elmethod
parámetro en lugar del encabezado HTTP....
Con respecto a los navegadores web comunes, hacen cumplir la Política del mismo origen y solo ejecutaránGET
solicitudes a servidores extranjeros. Aunque podría ser posible ejecutarPOST
solicitudes si el navegador web no aplica esos estándares web (error, malware).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 permitemethod=POST
, también podríabody={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 permitehttp://...?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.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
csrfToken
clave para la JWT y almacenar la JWT en una cookie consecure
yhttp-only
conjunto 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
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.
fuente