Pasé un tiempo confundido sobre el propósito de la solicitud de verificación previa, pero creo que lo tengo ahora.
La idea clave es que las solicitudes de verificación previa no son una cuestión de seguridad . Más bien, son una cosa que no cambia las reglas .
Las solicitudes de verificación previa no tienen nada que ver con la seguridad, y no tienen relación con las aplicaciones que se están desarrollando ahora, con conocimiento de CORS. Más bien, el mecanismo de verificación previa beneficia a los servidores que se desarrollaron sin tener conocimiento de CORS, y funciona como una comprobación de cordura entre el cliente y el servidor de que ambos son conscientes de CORS. Los desarrolladores de CORS sintieron que había suficientes servidores que confiaban en que nunca recibirían, por ejemplo, una solicitud DELETE de dominio cruzado de que inventaron el mecanismo de verificación previa para permitir que ambas partes se suscriban. Consideraron que la alternativa, que habría sido simplemente habilitar las llamadas entre dominios, habría roto demasiadas aplicaciones existentes.
Aquí hay tres escenarios:
Servidores antiguos, que ya no están en desarrollo y desarrollados antes que CORS. Estos servidores pueden suponer que nunca recibirán, por ejemplo, una solicitud DELETE entre dominios. Este escenario es el principal beneficiario del mecanismo de verificación previa. Sí, estos servicios ya podrían estar siendo maltratados por un agente de usuario malicioso o no conforme (y CORS no hace nada para cambiar esto), pero en un mundo con CORS, el mecanismo de verificación previa proporciona una 'verificación de estado' adicional para que los clientes y servidores no romper porque las reglas subyacentes de la web han cambiado.
Servidores que todavía están en desarrollo, pero que contienen mucho código antiguo y para los cuales no es factible / deseable auditar todo el código antiguo para asegurarse de que funcione correctamente en un mundo de dominio cruzado. Este escenario permite a los servidores optar progresivamente a CORS, por ejemplo, diciendo "Ahora permitiré este encabezado en particular", "Ahora permitiré este verbo HTTP en particular", "Ahora permitiré que las cookies / información de autenticación sean enviado ", etc. Este escenario se beneficia del mecanismo de verificación previa.
Nuevos servidores que están escritos con conocimiento de CORS. Según las prácticas de seguridad estándar, el servidor debe proteger sus recursos ante cualquier solicitud entrante: los servidores no pueden confiar en que los clientes no hagan cosas maliciosas. Este escenario no se beneficia del mecanismo de verificación previa : el mecanismo de verificación previa no brinda seguridad adicional a un servidor que ha protegido adecuadamente sus recursos.
¿Cuál fue la motivación detrás de la introducción de solicitudes de verificación previa?
Se introdujeron solicitudes de verificación previa para que un navegador pudiera estar seguro de que estaba tratando con un servidor compatible con CORS antes de enviar ciertas solicitudes. Esas solicitudes se definieron como aquellas que eran potencialmente peligrosas (cambio de estado) y nuevas (no posibles antes de CORS debido a la Política del mismo origen ). El uso de solicitudes de verificación previa significa que los servidores deben aceptar (respondiendo adecuadamente a la verificación previa) a los nuevos tipos de solicitud potencialmente peligrosos que CORS hace posible.
Ese es el significado de esta parte de la especificación : "Para proteger los recursos contra las solicitudes de origen cruzado que no pudieron originarse de ciertos agentes de usuario antes de que existiera esta especificación, se realiza una solicitud de verificación previa para garantizar que el recurso conozca esta especificación".
¿Puedes darme un ejemplo?
Imaginemos que un usuario del navegador inicia sesión en su sitio bancario en
A.com
. Cuando navegan a lo maliciosoB.com
, esa página incluye algunos Javascript que intenta enviar unaDELETE
solicitudA.com/account
. Dado que el usuario ha iniciado sesiónA.com
, esa solicitud, si se envía, incluiría cookies que identifiquen al usuario.Antes de CORS, la Política del mismo origen del navegador habría bloqueado el envío de esta solicitud. Pero dado que el propósito de CORS es hacer posible este tipo de comunicación de origen cruzado, ya no es apropiado.
El navegador simplemente puede enviar
DELETE
y dejar que el servidor decida cómo manejarlo. Pero, ¿y siA.com
no conoce el protocolo CORS? Podría seguir adelante y ejecutar lo peligrosoDELETE
. Podría haber asumido que, debido a la Política del mismo origen del navegador, nunca podría recibir una solicitud de este tipo y, por lo tanto, nunca podría haberse endurecido contra tal ataque.Para proteger dichos servidores que no son compatibles con CORS, entonces, el protocolo requiere que el navegador envíe primero una solicitud de verificación previa . Este nuevo tipo de solicitud es algo a lo que solo los servidores conscientes de CORS pueden responder correctamente, lo que permite al navegador saber si es seguro enviar el mensaje o no
DELETE
.¿Por qué todo este alboroto sobre el navegador, no puede el atacante simplemente enviar una
DELETE
solicitud desde su propia computadora?Claro, pero dicha solicitud no incluirá las cookies del usuario. El ataque que está diseñado para prevenir se basa en el hecho de que el navegador enviará cookies (en particular, información de autenticación para el usuario) para el otro dominio junto con la solicitud.
Eso suena como Cross-Site Request Falsificación , cuando un impreso en el sitio
B.com
lataPOST
queA.com
con las cookies del usuario y hacer daño.Así es. Otra forma de decir esto es que se crearon solicitudes de verificación previa para no aumentar la superficie de ataque CSRF para servidores que no son compatibles con CORS.
Pero al observar los requisitos para solicitudes "simples" que no requieren comprobaciones previas, veo que
POST
todavía está permitido. ¡Eso puede cambiar el estado y eliminar datos como unDELETE
!¡Es verdad! CORS no protege su sitio de los ataques CSRF. Por otra parte, sin CORS tampoco estás protegido de los ataques CSRF. El propósito de las solicitudes de verificación previa es limitar su exposición a CSRF a lo que ya existía en el mundo anterior a CORS.
Suspiro. OK, a regañadientes acepto la necesidad de solicitudes de verificación previa. Pero, ¿por qué tenemos que hacerlo para cada recurso (URL) en el servidor? El servidor maneja CORS o no lo hace.
¿Estás seguro de eso? No es raro que varios servidores manejen solicitudes para un solo dominio. Por ejemplo, puede darse el caso de que las solicitudes
A.com/url1
sean manejadas por un tipo de servidor y las solicitudesA.com/url2
sean manejadas por un tipo diferente de servidor. En general, no es el caso de que el servidor que maneja un solo recurso pueda garantizar la seguridad de todos los recursos en ese dominio.Multa. Hagamos un compromiso. Creemos un nuevo encabezado CORS que permita al servidor indicar exactamente para qué recursos puede hablar, de modo que se puedan evitar solicitudes de verificación previa adicionales a esas URL.
¡Buena idea! De hecho, el encabezado
Access-Control-Policy-Path
se propuso solo para este propósito. Sin embargo, en última instancia, se dejó fuera de la especificación, aparentemente porque algunos servidores implementaron incorrectamente la especificación URI de tal manera que las solicitudes a rutas que parecían seguras para el navegador no serían seguras en los servidores dañados.¿Fue una decisión prudente que priorizó la seguridad sobre el rendimiento, permitiendo a los navegadores implementar inmediatamente la especificación CORS sin poner en riesgo los servidores existentes? ¿O fue miope condenar Internet para desperdiciar ancho de banda y duplicar la latencia solo para acomodar errores en un servidor en particular en un momento determinado?
Las opiniones difieren.
Bueno, ¿al menos los navegadores almacenarán en caché la verificación previa para una sola URL?
Si. Aunque probablemente no por mucho tiempo. En los navegadores WebKit, el tiempo máximo de caché de verificación previa es actualmente de 10 minutos .
Suspiro. Bueno, si sé que mis servidores son compatibles con CORS y, por lo tanto, no necesitan la protección que ofrecen las solicitudes de verificación previa, ¿hay alguna forma de evitarlos?
Su única opción real es asegurarse de cumplir con los requisitos para solicitudes "simples". Eso podría significar omitir encabezados personalizados que de otro modo incluiría (como
X-Requested-With
), mentir sobre elContent-Type
o más.Hagas lo que hagas, debes asegurarte de tener las protecciones CSRF adecuadas, ya que la especificación CORS no aborda el rechazo de solicitudes "simples", incluidas las inseguras
POST
. Como dice la especificación : "los recursos para los que las solicitudes simples tienen una importancia distinta de la recuperación deben protegerse de la falsificación de solicitudes entre sitios".fuente
Considere el mundo de las solicitudes de dominio cruzado antes de CORS. Se podría hacer un formulario de envío estándar, o usar una
script
o unimage
tag para emitir una petición GET. No podría realizar ningún otro tipo de solicitud que no sea GET / POST, y no podría emitir ningún encabezado personalizado en estas solicitudes.Con el advenimiento de CORS, los autores de las especificaciones se enfrentaron al desafío de introducir un nuevo mecanismo de dominio cruzado sin romper la semántica existente de la web. Decidieron hacer esto dando a los servidores una forma de optar por cualquier tipo de solicitud nueva. Esta opción es la solicitud de verificación previa.
Por lo tanto, las solicitudes GET / POST sin ningún encabezado personalizado no necesitan una verificación previa, ya que estas solicitudes ya eran posibles antes de CORS. Sin embargo, cualquier solicitud con cabeceras personalizadas, o peticiones PUT / DELETE, no necesita una verificación previa, ya que estos son nuevos en la especificación CORS. Si el servidor no sabe nada sobre CORS, responderá sin ningún encabezado específico de CORS, y no se realizará la solicitud real.
Sin la solicitud de verificación previa, los servidores podrían comenzar a ver solicitudes inesperadas de los navegadores. Esto podría generar un problema de seguridad si los servidores no estuvieran preparados para este tipo de solicitudes. La verificación previa de CORS permite que las solicitudes entre dominios se introduzcan en la web de manera segura.
fuente
CORS le permite especificar más encabezados y tipos de métodos de los que anteriormente era posible con origen cruzado
<img src>
o<form action>
.Algunos servidores podrían haber estado (mal) protegidos con la suposición de que un navegador no puede realizar, por ejemplo,
DELETE
solicitud de origen cruzado o solicitud de origen cruzado conX-Requested-With
encabezado, por lo que tales solicitudes son "confiables".Para asegurarse de que el servidor realmente es compatible con CORS y no solo responde a solicitudes aleatorias, se ejecuta la verificación previa.
fuente
Aquí hay otra forma de verlo, usando código:
Pre-CORS, el intento de explotación anterior fallaría porque viola la política del mismo origen. Una API diseñada de esta manera no necesitaba protección XSRF, porque estaba protegida por el modelo de seguridad nativo del navegador. Era imposible que un navegador anterior a CORS generara una POST JSON de origen cruzado.
Ahora CORS entra en escena: si no era necesario optar por CORS a través del vuelo previo, de repente este sitio tendría una gran vulnerabilidad, sin culpa propia.
Para explicar por qué algunas solicitudes pueden omitir el pre-vuelo, esto se responde mediante la especificación:
Para desenredar eso, GET no se vuela previamente porque es un "método simple" como se define en 7.1.5. (Los encabezados también deben ser "simples" para evitar el pre-vuelo). La justificación de esto es que la solicitud GET de origen cruzado "simple" ya podría realizarse, por ejemplo,
<script src="">
(así es como funciona JSONP). Dado que cualquier elemento con unsrc
atributo puede desencadenar un GET de origen cruzado, sin pre-vuelo, no habría ningún beneficio de seguridad al requerir una pelea previa en XHR "simples".fuente
Siento que las otras respuestas no se centran en la razón por la que la lucha previa mejora la seguridad.
Escenarios:
1) Con pre-vuelo . Un atacante falsifica una solicitud del sitio dummy-forums.com mientras el usuario se autentica en safe-bank.com.
Si el servidor no verifica el origen, y de alguna manera tiene una falla, el navegador emitirá una solicitud previa al vuelo, OPCIÓN método. El servidor no conoce ninguno de los CORS que el navegador espera como respuesta, por lo que el navegador no continuará (sin ningún daño)
2) Sin pre-vuelo . Un atacante falsifica la solicitud en el mismo escenario que el anterior, el navegador emitirá la solicitud POST o PUT de inmediato, el servidor la acepta y podría procesarla, lo que podría causar algún daño.
Si el atacante envía una solicitud directamente, de origen cruzado, desde algún host aleatorio, lo más probable es que uno esté pensando en una solicitud sin autenticación. Esa es una solicitud falsificada, pero no una xsrf. entonces el servidor verificará las credenciales y fallará. CORS no intenta evitar que un atacante que tenga las credenciales para emitir solicitudes, aunque una lista blanca podría ayudar a reducir este vector de ataque.
El mecanismo previo al vuelo agrega seguridad y consistencia entre clientes y servidores. No sé si vale la pena el apretón de manos adicional para cada solicitud, ya que el almacenamiento en caché es muy útil allí, pero así es como funciona.
fuente
Fuente
fuente
Las solicitudes previas al vuelo son necesarias para las solicitudes que pueden cambiar de estado en el servidor. Hay 2 tipos de solicitudes:
1) Llamadas que no pueden cambiar el estado en el servidor (como GET) : el usuario puede obtener una respuesta a la solicitud (si el servidor no verifica el origen) pero si el dominio solicitante no se agrega al encabezado de respuesta Access-Control- Permitir-Origen, el navegador no muestra los datos al usuario, es decir, la solicitud se envía desde el navegador pero el usuario no puede ver / hacer uso de la respuesta.
2) Llamadas que pueden cambiar el estado en el servidor (como POST, DELETE) : dado que en 1), vemos que el navegador no bloquea la solicitud, sino la respuesta, no se debe permitir realizar cambios de estado sin verificaciones previas . Dichas llamadas pueden realizar cambios en un servidor de confianza que no verifica el origen de las llamadas (denominado falsificación de solicitudes de sitios cruzados), aunque la respuesta al navegador podría ser un error. Por esta razón, tenemos el concepto de solicitudes previas al vuelo que realizan una llamada de OPCIONES antes de que se puedan enviar al servidor las llamadas que cambien de estado.
fuente
¿No son las solicitudes previamente verificadas sobre rendimiento ? Con las solicitudes con verificación previa, un cliente puede saber rápidamente si la operación está permitida antes de enviar una gran cantidad de datos, por ejemplo, en JSON con el método PUT. O antes de viajar datos confidenciales en encabezados de autenticación a través del cable.
El hecho de PUT, DELETE y otros métodos, además de los encabezados personalizados, no están permitidos por defecto (necesitan permiso explícito con "Access-Control-Request-Methods" y "Access-Control-Request-Headers"), eso suena al igual que una verificación doble, porque estas operaciones podrían tener más implicaciones para los datos del usuario, en lugar de solicitar GET. Entonces, suena como:
"Vi que permitía solicitudes entre sitios desde http: //foo.example , PERO ¿ ESTÁ SEGURO de que permitirá solicitudes ELIMINAR? ¿Consideró los impactos que estas solicitudes podrían causar en los datos del usuario?"
No entendí la correlación citada entre las solicitudes con verificación previa y los beneficios de los servidores antiguos. Un servicio web que se implementó antes de CORS, o sin un conocimiento de CORS, nunca recibirá NINGUNA solicitud entre sitios, porque primero su respuesta no tendrá el encabezado "Access-Control-Allow-Origin".
fuente
En un navegador compatible con CORS, las solicitudes de lectura (como GET) ya están protegidas por la política del mismo origen: un sitio web malicioso que intente realizar una solicitud de dominio cruzado autenticado (por ejemplo, al sitio web de banca por Internet de la víctima o la interfaz de configuración del enrutador) poder leer los datos devueltos porque el banco o el enrutador no establece el
Access-Control-Allow-Origin
encabezado.Sin embargo, al escribir solicitudes (como POST), el daño se hace cuando la solicitud llega al servidor web. * Un servidor web podría verificar el
Origin
encabezado para determinar si la solicitud es legítima, pero esta verificación a menudo no se implementa porque el servidor web no tiene necesidad para CORS o el servidor web es más antiguo que CORS y, por lo tanto, supone que las POST de dominio cruzado están completamente prohibidas por la política del mismo origen.Es por eso que los servidores web tienen la oportunidad de optar por recibir solicitudes de escritura entre dominios .
* Esencialmente, la versión AJAX de CSRF.
fuente