¿Cómo evitar que otros sitios web envíen solicitudes AJAX de dominio cruzado?

4

Desde dos aplicaciones diferentes, pude enviar solicitudes de origen cruzado. Aunque el navegador devuelve un error de "origen cruzado", mi servidor todavía está recibiendo y ejecutando la solicitud. Por ejemplo, desde un sitio remoto puedo invocar una solicitud de dominio cruzado usando

$.ajax({
        xhrFields: {
            withCredentials: true
        },
        data:{ my: 'a' },
        url: 'http://MyApp/Page',
        type: 'POST'
})

Sé que el navegador no devuelve la respuesta al script, pero la página de mi servidor todavía se ejecuta.

Digamos que un usuario inocente ha iniciado sesión en un sitio http://example.com . Esta aplicación aceptará solicitudes POST para insertar un registro. Cuando el usuario inocente visita http://HackerSite.com , el http://HackerSite.com podrá enviar una solicitud POST a http://example.com a través de AJAX. ¿Cómo se puede prevenir esto?

    
pregunta user960567 24.10.2013 - 20:19
fuente

4 respuestas

16

Además de a través de una solicitud AJAX de dominio cruzado con credenciales, el POST en su ejemplo también podría enviarse utilizando un formulario estándar sin AJAX:

<form method="post" action="http://MyApp/Page" name="hiddenFormInIframe">

<input type="hidden" name="my" value="a" />

</form>
<script type="text/javascript">
  document.hiddenFormInIframe.submit();
</script>

Esto también incluiría cookies en la solicitud.

La vulnerabilidad de la que está hablando se llama falsificación de solicitudes entre sitios .

Puede evitar que la POST se envíe desde otro dominio enviando un encabezado en su solicitud AJAX y luego verificando el lado del servidor de encabezado. Un encabezado común para usar es X-Requested-With . Este encabezado no puede enviarse a través de AJAX a través de AJAX debido a que este encabezado no está en la lista segura (sin CORS siendo habilitado en su servidor). Un formulario HTML tampoco puede enviar este encabezado.

Solo se permiten los siguientes encabezados de dominio cruzado a través de AJAX:

  
  • aceptar
  •   
  • Aceptar-Idioma
  •   
  • contenido-lenguaje
  •   
  • ID del último evento
  •   
  • Tipo de contenido
  •   

El encabezado X-Requested-With se establece automáticamente cuando se usa JQuery y puede verificar esto en su código ASP.NET .

Sin embargo, en el pasado ha habido algunas vulnerabilidades a través de complementos como Flash donde se podrían configurar encabezados que no eran posibles a través de un navegador (por ejemplo, Referer ), por lo que para protegerse de esto, se recomienda utilizar patrón de token del sincronizador que implica configurar un token en un campo oculto o en un encabezado. Este token se validará, así como la cookie de autenticación para todas las solicitudes con efectos secundarios. Es decir, solicitudes que cambian, envían o eliminan (normalmente POST).

Para obtener más información sobre CORS, consulte aquí: enlace

    
respondido por el SilverlightFox 10.11.2013 - 21:52
fuente
2

Las políticas entre dominios impiden que los dominios lean información en algunas circunstancias de otros dominios que no lo permiten explícitamente con encabezados CORS . Pero, eso no prohíbe que salgan las solicitudes de origen cruzado. La solicitud en su ejemplo debe estar marcada como " pre-flight " OPTIONS request : una solicitud de sondeo para ver si la solicitud" real "tendrá éxito.

Parte de la solución puede ser terminar las solicitudes OPTIONS al inicio del proceso: tan pronto como se pueda determinar si se permite el acceso al dominio de sondeo.

Una solución más completa puede incluir tokens de acceso a la API. En cada carga de página, genere e incruste un token de acceso. Incluir ese token en todas las solicitudes API / AJAX. Cualquier solicitud que no incluya el token debe finalizar antes.

    
respondido por el svidgen 02.09.2014 - 16:50
fuente
2

La mejor idea aquí es que, como se ha dicho, use tokens CSRF. La forma más sencilla es agregar la dirección IP de los usuarios como un identificador en una base de datos y luego agregar un valor aleatorio para esta IP. El valor aleatorio es el token correcto.

Por ejemplo, cuando alguien visita su página para obtener el formulario, tome la IP de los usuarios, digamos: 12.12.12.12.

Agregar a una base de datos clave-valor junto con un valor aleatorio: 12.12.12.12 = ljghsdlghdlghdlshsdflgd (nota, NO use el ejemplo "ljghsdlghdlghdlshsdflgd", en su lugar genere un valor pseudoaleatorio de una longitud suficiente)

Agregue este valor pseudoaleatorio como un campo oculto.

Al enviar, use la IP de los usuarios para buscar la respuesta sugerida. Si la respuesta real coincide con la respuesta sugerida, se acepta la solicitud. En CUALQUIER intento de envío (independientemente del éxito o no), elimine el registro en la base de datos, si existe alguno. Esto significa que cualquier intento de CSRF invalidará los tokens reales para el usuario objetivo, y cada token será de un solo uso. Dependiendo de qué tipo de base de datos sea, es simple configurar la clave en "" o simplemente eliminarla.

Me gusta: 12.12.12.12="".

Una buena idea es también vencer estos valores por tiempo, tanto por seguridad como por deshacerse de datos innecesarios en la base de datos. Dependiendo de si es un foro, puede ser conveniente tener un par de horas como tiempo de validez, mientras que si es una forma simple de decirlo, cambiar una contraseña, entonces es suficiente con aproximadamente 5 minutos como tiempo de validez.

Otra idea es captcha, que también evita los ataques automáticos del lado del cliente, como infecciones de virus y troyanos de control remoto automatizados. Dependiendo de la sensibilidad de la aplicación web, puede ser una buena idea usar tokens Captcha AND CSRF al unísono. No siga el consejo de usar el mismo token para una sesión completa, es una mala idea en cuanto a seguridad, ya que existe una pequeña posibilidad de que el usuario pueda ser engañado para que envíe un token a un atacante también al sitio. Un token de un solo uso será inútil para el atacante, pero un token de uso múltiple puede ser tan peligroso como una sesión, cuyo CSRF está diseñado para proteger.

Por lo tanto, usar tokens de un solo uso, es la mejor seguridad en comparación con los tokens de uso múltiple, y también los tokens de un solo uso no necesitan estar protegidos en tránsito como lo sugiere el artículo de CSRF en una de las otras respuestas.

    
respondido por el sebastian nielsen 03.09.2014 - 06:39
fuente
1

La página del servidor no debería ejecutarse si tiene todo configurado correctamente. La solicitud debe rechazarse antes de que tenga la oportunidad de llegar tan lejos en la línea.

Sospecho que ha configurado su aplicación / servidor para que Access-Control-Allow-Origin esté establecido en * . Hay una serie de lugares en los que se puede hacer esto, pero uno común para la aplicación asp.net se encuentra en web.config (s) Ejemplo:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
  </customHeaders>
</httpProtocol>

Verificaría si tiene este conjunto en algún lugar de su aplicación. Tenga en cuenta que asp.net puede tener varios archivos web.config y usará la configuración de la más cercana. Por ejemplo, digamos que tiene la siguiente estructura de directorios:

/MyProject/ajax/stuff

Si tienes un web.config en tu directorio MyProject y un web.config en tu directorio stuff , los archivos en stuff usarán el web.config desde stuff donde sea posible.

Hazme saber si eso es confuso.

Además, creo que esto también se puede configurar en IIS, así que eche un vistazo a sus encabezados allí también.

    
respondido por el Abe Miessler 24.10.2013 - 20:35
fuente

Lea otras preguntas en las etiquetas