2010-07-23 3 views
21

Estoy trabajando en una aplicación completamente ajax impulsado por que todas las solicitudes pasan a través de lo que básicamente equivale a un controlador principal que, en sus huesos desnudos, se ve algo como esto:¿Es suficiente una comprobación del servidor de encabezado X-Requested With para proteger contra un CSRF para una aplicación impulsada por ajax?

if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { 
    fetch($page); 
} 

¿Es esta generalmente suficiente para proteger contra falsificaciones de solicitudes entre sitios?

Es bastante inconveniente tener un token rotativo cuando no se actualiza toda la página con cada solicitud.

Supongo que podría pasar y actualizar el token único como una variable javascript global con cada solicitud, pero de alguna manera se siente torpe y parece intrínsecamente inseguro de todos modos.

EDITAR - Quizás un token estático, como el UUID del usuario, sería mejor que nada?

EDIT # 2 - Como The Rook señaló, esta podría ser una pregunta desgarradora. He leído especulaciones en ambos sentidos y escuché rumores lejanos sobre versiones anteriores de flash que pueden explotarse para este tipo de travesuras. Como no sé nada de eso, estoy ofreciendo una recompensa para cualquiera que pueda explicar cómo esto es un riesgo de CSRF. De lo contrario, lo estoy dando a Artefacto. Gracias.

+0

para el registro Artefacto era correcto. Debe leer el manual de seguridad del navegador en lugar de preguntar SO. Muchas de las respuestas sobre SO son incorrectas, especialmente para temas de división de cabello como este. – rook

+0

Hubo algunas [vulnerabilidades] (http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_Flash) en versiones anteriores de flash. Sin embargo, para los usuarios que realmente están ejecutando estas versiones anteriores de Flash, diría que los ataques de CSRF son el menor de sus problemas cuando se enfrentan con vulnerabilidades de ejecución de código arbitrario. – Artefacto

+0

http://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requestted-with-header | http://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token –

Respuesta

13

Yo diría que es suficiente. Si se permitieran solicitudes entre dominios, estaría condenado de todos modos porque el atacante podría usar Javascript para obtener el token CSRF y usarlo en la solicitud falsificada.

Una ficha estática no es una gran idea. El token se debe generar al menos una vez por sesión.

EDIT2 Mike no tiene razón después de todo, lo siento. No había leído la página a la que me había vinculado correctamente. Dice:

Una petición en sitios cruzados simple es aquella que: [...] no establece encabezados personalizados con la petición HTTP (tal como X-Modificado, etc.)

Por lo tanto, si configura X-Requested-With, la solicitud debe realizarse previamente, y a menos que responda a la solicitud previa al vuelo OPTIONS que autoriza la solicitud entre sitios, no se realizará.

EDIT Mike tiene razón, a partir de Firefox 3.5, XMLHttpRequests entre sitios es permitted. En consecuencia, también debe verificar si el encabezado Origin, cuando existe, coincide con su sitio.

if (array_key_exists('HTTP_ORIGIN', $_SERVER)) { 
    if (preg_match('#^https?://myserver.com$#', $_SERVER['HTTP_ORIGIN']) 
     doStuff(); 
} 
elseif (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && 
     (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) 
    doStuff(); 
+0

Para el caballero que me votó: ¿puedes explicar qué pasa con mi respuesta? – Artefacto

+0

Es una mala respuesta porque solo agregar algo al encabezado no ofrece absolutamente ninguna protección porque se puede falsificar fácilmente. Vea la respuesta aceptada para una buena solución al problema. –

+0

@musicfreak Este encabezado se agrega solo cuando la solicitud se realiza a través de Javascript. CSRF no se puede lograr con Javascript debido a restricciones entre sitios. En consecuencia, es suficiente. Claro que podrías "forjar" el encabezado, p. construyendo un navegador que siempre enviaría este encabezado. Pero al hacerlo, te dispararías en el pie. La protección contra CRFS es protección para los usuarios ** de ellos mismos **, frente a las solicitudes maliciosas y programaticamente hechas por ellos mismos. – Artefacto

0

No creo que esto ofrezca ningún tipo de protección. Un sitio de ataque aún puede usar xmlhttprequest para su solicitud entre sitios eludir su verificación.

+0

¿Conoces una solución adecuada? No tienes que sostener mi mano y guiarme a través de ella, pero ¿quizás podrías señalarme en la dirección correcta? :) – Greg

+0

@Greg: No, en realidad no. Estaba pensando que usar un token de un solo uso es el camino a seguir. Pero no tengo experiencia con eso. – Alex

0

Respuesta corta: no. Cualquier atacante simplemente usaría Ajax para atacar su sitio web. Debe generar un token aleatorio con un tiempo de vida corto pero no demasiado largo que actualizaría durante cada solicitud de Ajax.

Debería usar una matriz de tokens en javascript ya que puede tener varias solicitudes ajax ejecutándose al mismo tiempo.

+2

¿Tenía la impresión de que no se permiten las solicitudes AJAX entre dominios? ¿Supongo que hay soluciones? – Greg

+0

El atacante puede usar Firebug o una consola de otro desarrollador para AJAX en el dominio. –

+2

-1, ¿te importa escribir un exploit para hacer una copia de seguridad de ese comentario? ¿No? No lo creo. xmlhttprequest no puede cruzar el sitio, es una violación de la misma política de origen. puede que no sea un método fuerte de desafío, pero no se puede escribir un exploit para esto. Lea el manual de seguridad del navegador de Google. – rook

0

Lo que está haciendo es seguro porque xmlhttprequest generalmente no es vulnerable a la falsificación de solicitudes entre sitios.

ya que este es un problema en el cliente, la forma más segura sería la de comprobar la arquitectura de seguridad de cada navegador :-)

(Este es un resumen; Estoy añadiendo esta respuesta porque esta pregunta es muy confuso, veamos qué dicen los votos)

1

No creo que esto sea seguro. Las mismas políticas de origen están diseñadas para evitar que los documentos de diferentes dominios accedan al contenido que se devuelve desde un dominio diferente. Esta es la razón por la cual los problemas XSRF existen en primer lugar. En general, a XSRF no le importa la respuesta. Se utiliza para ejecutar un tipo específico de solicitud, como una acción de eliminación. En la forma más simple, esto se puede hacer con una etiqueta IMG formateada correctamente. Su solución propuesta evitaría esta forma más simple, pero no protege a alguien de usar el objeto XMLHttp para realizar la solicitud. Debe usar las técnicas de prevención estándar para XSRF. Me gusta generar un número aleatorio en JavaScript y agregarlo a la cookie y una variable de formulario. Esto asegura que el código también puede escribir cookies para ese dominio. Si desea más información, consulte this entry.

Además, para evitar que los comentarios sobre XMLHttp no funcionen en el script. Usé el siguiente código con firefox 3.5 para hacer una solicitud a google desde html corriendo en el dominio localhost. El contenido no será devuelto, pero usando Firebug, puede ver que se realiza la solicitud.

<script> 
var xmlhttp = false; 

if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { 
    try { 
     xmlhttp = new XMLHttpRequest(); 
    } catch (e) { 
     xmlhttp = false; 
    } 
} 
if (!xmlhttp && window.createRequest) { 
    try { 
     xmlhttp = window.createRequest(); 
    } catch (e) { 
     xmlhttp = false; 
    } 
} 

xmlhttp.open("GET", "http://www.google.com", true); 
xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
     alert("Got Response"); 
     alert(xmlhttp.responseText) 
    } 
} 

xmlhttp.send(null) 
alert("test Complete"); 

+0

lo siento, tuve que editarlo para poder eliminar mi voto popular. – Artefacto

+0

Se lo doy a Artefacto, porque parece que X-Solicitado-Con no pasa, pero esto fue interesante. Gracias. – Greg

Cuestiones relacionadas