2008-09-27 10 views
15

Django viene con CSRF protection middleware, que genera un token único por sesión para usar en formularios. Escanea todas las solicitudes POST entrantes para el token correcto y rechaza la solicitud si el token falta o no es válido.¿Es seguro exponer el token de protección CSRF de una sesión?

Me gustaría usar AJAX para algunas solicitudes POST, pero dichas solicitudes no tienen el token CSRF disponible. Las páginas no tienen elementos <form> para enganchar y prefiero no ensuciar el marcado insertando el token como un valor oculto. Me parece que una buena forma de hacerlo es mostrar una fuente como /get-csrf-token/ para devolver el token del usuario, confiando en las reglas de scripts entre sitios del navegador para evitar que los sitios hostiles lo soliciten.

¿Es esta una buena idea? ¿Hay mejores formas de protegerse contra los ataques de CSRF al mismo tiempo que se permiten las solicitudes de AJAX?

Respuesta

11

Si sabe que va a necesitar el token CSRF para las solicitudes AJAX, siempre puede incrustarlo en el HTML en alguna parte; luego puedes encontrarlo a través de Javascript atravesando el DOM. De esta manera, todavía tendrá acceso al token, pero no lo expondrá a través de una API.

Dicho de otra manera: hágalo a través de las plantillas de Django, no a través del despachador de URL. Es mucho más seguro de esta manera.

+1

Los tokens CSRF deben cambiar con cada operación. ¿Sugiere que cada operación actualice el token? ¿Eso no significa que las operaciones del usuario tendrán que ser sincrónicas (el segundo no puede comenzar hasta que el primero haya regresado y se haya dado el nuevo token csrf)? – Mystic

+0

Esta no es la mejor respuesta. Como dice Carl Meyer en su respuesta: no es necesario proteger las solicitudes AJAX de CSRF mediante el uso de un token * en Django *, ya que Django ya protege las solicitudes AJAX de una manera diferente. Esto también elimina la preocupación de Mystics. – hopla

+1

tal vez esto ayude, incluso si no ordené esta historia sobre ajax y CSRF http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax – amirouche

0

Cancelar eso, estaba equivocado. (Consulte los comentarios.) Puede evitar el exploit asegurándose de que su JSON cumpla con la especificación: Siempre asegúrese de devolver un objeto literal como el objeto de nivel superior. (No puedo garantizar que no haya más exploits. Imagine un navegador que proporciona acceso al código fallido en su ventana. ¡Eventos de error!)

No puede confiar en las reglas de scripts entre sitios para mantener AJAX respuestas privadas. Por ejemplo, si devuelve el token CSRF como JSON, un sitio malicioso podría redefine the String or Array constructor y solicitar el recurso.

bigmattyh es correcto: debe incrustar el token en algún lugar de la marca. Alternativamente, puede rechazar cualquier POST que haga tenga un referer que no coincida con. De esta forma, solo las personas con firewalls de software excesivamente celosos serán vulnerables a CSRF.

+0

Uf, ese enlace de nuevo. Al menos el autor ha agregado una nota al final que él está equivocado. De hecho, JSON no es vulnerable a la redefinición de constructores, porque el analizador de Javascript generará una excepción cuando intente analizar un JSON sin adornos. –

16

ACTUALIZACIÓN: Lo siguiente era cierto, y debería ser cierto si todos los navegadores y complementos se implementaran correctamente. Desafortunadamente, ahora sabemos que no lo están, y que ciertas combinaciones de complementos y redireccionamientos del navegador pueden permitir que un atacante proporcione encabezados arbitrarios en una solicitud entre dominios. Desafortunadamente, esto significa que incluso las solicitudes AJAX con el encabezado "X-Requerido-Con: XMLHttpRequest" ahora deben estar protegidas por CSRF. Como resultado, Django no longer exempts Ajax requests from CSRF protection.

respuesta original

Vale la pena mencionar que la protección de peticiones AJAX de CSRF es innecesaria, ya que los navegadores no permiten que entre sitios peticiones AJAX. De hecho, el middleware Django CSRF ahora automatically exempts AJAX requests from CSRF token scanning.

Esto solo es válido si realmente está revisando el lado del servidor de encabezado X-Requerido para el valor "XMLHttpRequest" (que hace Django), y solo exime las solicitudes AJAX reales del escaneo CSRF.

+0

Esto no es verdad. Una solicitud de Ajax obviamente se está comunicando con un servidor (el suyo). Como atacante, aún puedo crear las mismas solicitudes de publicación desde cualquier otro sitio a través de diferentes métodos, y sin protección CSRF, tendré éxito si el usuario inicia sesión. – Nathan

+2

@Nathan No puede "crear las mismas solicitudes de publicación desde cualquier lugar". más a través de una serie de métodos diferentes ", porque el navegador se negará a ejecutar esa solicitud posterior (a menos que pueda obtener mi dominio para servir a su JS, en cuyo caso, obviamente, tengo otro agujero). Tendría que omitir las restricciones del mismo dominio o engañar al navegador de un usuario para que realice una solicitud que no sea AJAX y simulando el encabezado X-Requerido-Con. De cualquier manera, si puedes hacerlo, es un error del navegador. Demostraciones de trabajo bienvenidas –

+0

@Carl Meyer: Todavía estoy en desacuerdo. Puedo (por ejemplo) atraer a un usuario a un sitio web bajo mi control que hace una publicación en el servidor de la misma manera que lo hace la solicitud AJAX, no es necesario inyectar javascript en su sitio. No hay restricciones del mismo dominio en una publicación HTTP normal: puedo publicar con cualquier formulario en cualquier dominio. Las cookies se envían con la solicitud, no con la página. Esto todavía cae dentro de la categoría de Cross-Site-Request-Forgery. – Nathan

Cuestiones relacionadas