¿Cómo manejar la protección CSRF en una aplicación de una sola página?

4

Actualmente estoy creando una aplicación de una sola página con una interfaz de JavaScript / HTML. El front-end realiza llamadas a una API WEB que fue escrita en .NET. Actualmente tengo una página HTML donde un usuario ingresa sus credenciales y hace clic en iniciar sesión. Luego, se envía una solicitud AJAX a la API WEB que autentica al usuario y devuelve una cookie solo de HTTP que contiene un token web de Json. El navegador luego envía esta cookie en cada solicitud posterior, y el controlador la valida.

Lo anterior funciona bien, sin embargo, carece de protección CSRF. Estoy tratando de descubrir la mejor manera de implementar esto. De mi investigación, parece que hay algunas opciones.

  1. El artículo en enlace sugiere extraer un token de una cookie y luego enviarlo como un encabezado de solicitud. Para hacer esto, necesitaría quitar la marca HTTP-Only, para que JavaScript pueda acceder a la cookie. No creo que esta sea la mejor solución, ya que podría exponer la información de la sesión si se encuentra una vulnerabilidad XSS. ¿Hay algo que este olvidando?

  2. En otro lugar, leí sobre el envío de una cookie separada que contenía el token CSRF y sacaba el valor con JavaScript. Luego, envíe ese valor como un encabezado personalizado en las solicitudes subsiguientes de AJAX y haga que la API WEB se valide basándose en ese encabezado. Escribí una aplicación de prueba de concepto rápida para esto y descubrí que el navegador aún enviará la cookie en la que se entregó el token CSRF en futuras solicitudes. ¿Esto plantea un problema? ¿Podría una página con un ataque CSRF explotar esto de alguna manera?

  3. Similar a lo anterior, pero en lugar de entregar el token CSRF a través de una cookie, envíelo a través de un encabezado personalizado y haga que JavaScript lo lea desde allí. Esto parece que es el más sencillo, pero ¿ve algún inconveniente con este enfoque?

Además, ¿es seguro seguir usando un solo token CSRF para la sesión completa de un usuario, o debería actualizarse en cada solicitud?

    
pregunta Dave 04.01.2017 - 18:11
fuente

2 respuestas

1

Puede usar las estrategias de token CSRF clásicas, pero pueden hacer un esfuerzo incómodo para usarlas en aplicaciones basadas en AJAX, y hay opciones más sencillas disponibles para los puntos finales específicos de AJAX:

  • Agregue un encabezado adicional a las solicitudes de su servidor como "X-Request-With: XMLHttpRequest" o "X-Is-Local-XHR: true", y haga que su servidor requiera el encabezado de las solicitudes autenticadas. Los usuarios con versiones anteriores de Flash pueden ser vulnerables (aunque las versiones anteriores de Flash también tienen vulnerabilidades mucho peores, por lo que su elección es importante para usted). Consulte enlace

  • Verifique que el encabezado de Origen o del Referer esté configurado y coincida con el dominio en el encabezado del Host. El encabezado de origen se envía para todas las solicitudes POST de Chrome y Firefox, pero es posible que los navegadores más antiguos no lo incluyan. El encabezado del Referer está deshabilitado por algunos usuarios por razones de privacidad. La presencia de cualquiera de los dos con un valor válido es suficiente para verificar la solicitud.

respondido por el Macil 05.01.2017 - 02:17
fuente
1

Este es un tema antiguo y hay muchas discusiones dispersas (incluso aquí en Security.SE). Sin embargo, en lugar de la sugerencia común de emular un esquema de protección CSRF basado en cookies y post-back, le propongo que elimine las cookies por completo.

Trate su aplicación de una sola página como una aplicación real y haga que se autentique a las API web utilizando los métodos estándar. Por ejemplo, puede usar tokens de OAuth y solicitudes sin sesión. (Si OAuth es demasiado difícil de configurar, podría usar un esquema de token personalizado).

Esto también resuelve problemas con CORS.

    
respondido por el billc.cn 04.01.2017 - 18:37
fuente

Lea otras preguntas en las etiquetas