Por qué necesitas el "aislamiento de origen cruzado" para obtener funciones potentes

Descubre por qué es necesario el aislamiento de origen cruzado para usar funciones potentes como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() y un temporizador de alta resolución con mayor precisión.

Domenic Denicola
Domenic Denicola

Introducción

En Cómo hacer que tu sitio web esté "aislado con origen cruzado" con COOP y COEP, explicamos cómo adoptar un estado "aislado de origen cruzado" con COOP y COEP. En este artículo complementario, se explica por qué es necesario el aislamiento de origen cruzado para habilitar funciones potentes en el navegador.

Información general

La Web se basa en la política del mismo origen: una función de seguridad que restringe la forma en que los documentos y las secuencias de comandos pueden interactuar con recursos de otro origen. Este principio restringe las formas en que los sitios web pueden acceder a los recursos de origen cruzado. Por ejemplo, un documento de https://a.example no puede acceder a los datos alojados en https://b.example.

Sin embargo, la política del mismo origen tuvo algunas excepciones históricas. Cualquier sitio web puede hacer lo siguiente:

  • Cómo incorporar iframes de origen cruzado
  • Incluye recursos de origen cruzado, como imágenes o secuencias de comandos
  • Abrir ventanas emergentes de origen cruzado con una referencia de DOM

Si la Web pudiera diseñarse desde cero, estas excepciones no existirían. Lamentablemente, para cuando la comunidad web se dio cuenta de los beneficios clave de una política estricta del mismo origen, la Web ya contaba con estas excepciones.

Los efectos secundarios de seguridad de una política laxa del mismo origen se corrigieron de dos maneras. Una de ellas fue la introducción de un protocolo nuevo llamado Uso compartido de recursos multiorigen (CORS) cuyo propósito es garantizar que el servidor permita compartir un recurso con un origen determinado. La otra forma consiste en quitar de forma implícita el acceso directo de la secuencia de comandos a los recursos de origen cruzado mientras se conserva la retrocompatibilidad. Estos recursos de origen cruzado se denominan recursos “opacos”. Por ejemplo, es el motivo por el que falla la manipulación de los píxeles de una imagen de origen cruzado mediante CanvasRenderingContext2D, a menos que se aplique CORS a la imagen.

Todas estas decisiones sobre políticas se aplican a un grupo de contexto de navegación.

Grupo de contexto de navegación

Durante mucho tiempo, la combinación de CORS y recursos opacos fue suficiente para que los navegadores fueran seguros. A veces, se descubrieron casos extremos (como las vulnerabilidades de JSON) y se debían aplicar parches, pero, en general, el principio de no permitir el acceso directo de lectura a los bytes sin procesar de los recursos de origen cruzado era correcto.

Todo esto cambió con Spectre, que hace que cualquier dato que se cargue en el mismo grupo de contexto de navegación donde tu código pueda leerse. Cuando se mide el tiempo que tardan ciertas operaciones, los atacantes pueden adivinar el contenido de las cachés de la CPU y, a través de eso, el contenido de la memoria del proceso. Esos ataques de tiempo son posibles con cronómetros de bajo nivel de detalle que existen en la plataforma, pero pueden acelerarse con cronómetros de alto nivel de detalle, tanto explícitos (como performance.now()) como implícitos (como SharedArrayBuffer). Si evil.com incorpora una imagen de origen cruzado, puede usar un ataque Spectre para leer sus datos de píxeles, lo que hace que las protecciones basadas en la "opacidad" dejen de ser efectivas.

Espectro

Idealmente, el servidor propietario del recurso debe verificar de forma explícita todas las solicitudes de origen cruzado. Si el servidor propietario de recursos no proporciona la verificación, los datos nunca llegarán al grupo contextual de navegación de una persona malintencionada y, por lo tanto, estarán fuera del alcance de cualquier ataque Spectre que pueda llevar a cabo una página web. Lo llamamos un estado aislado de origen cruzado. De esto se trata COOP+COEP.

En un estado aislado de origen cruzado, el sitio solicitante se considera menos peligroso y desbloquea funciones potentes, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() y temporizadores de alta resolución con mayor precisión, que podrían usarse en otros ataques similares a Spectre. También evita modificar document.domain.

Política de incorporaciones de origen cruzado

La Política de incorporaciones de origen cruzado (COEP) evita que un documento cargue recursos de origen cruzado que no otorguen el permiso del documento de forma explícita (mediante CORP o CORS). Con esta función, puedes declarar que un documento no puede cargar esos recursos.

Cómo funciona el COEP

Para activar esta política, agrega el siguiente encabezado HTTP al documento:

Cross-Origin-Embedder-Policy: require-corp

La palabra clave require-corp es el único valor aceptado para COEP. Esto aplica la política de que el documento solo puede cargar recursos del mismo origen o recursos marcados explícitamente como cargas desde otro origen.

Para que los recursos se puedan cargar desde otro origen, deben ser compatibles con el uso compartido de recursos entre dominios (CORS) o la política de recursos entre dominios (CORP).

Uso compartido de recursos entre dominios

Si un recurso de origen cruzado admite el uso compartido de recursos entre dominios (CORS), puedes usar el atributo crossorigin para cargarlo en tu página web sin que el COEP lo bloquee.

<img src="https://third-party.example.com/image.jpg" crossorigin>

Por ejemplo, si este recurso de imagen se entrega con encabezados CORS, usa el atributo crossorigin para que la solicitud para recuperar el recurso use el modo CORS. Esto también evita que la imagen se cargue, a menos que establezca encabezados de CORS.

De manera similar, puedes recuperar datos de origen cruzado a través del método fetch(), que no requiere un control especial, siempre y cuando el servidor responda con los encabezados HTTP correctos.

Política de recursos entre dominios

La Política de recursos multiorigen (CORP) se introdujo originalmente como una opción de aceptación para proteger tus recursos y evitar que otro origen cargue tus recursos. En el contexto de COEP, CORP puede especificar la política del propietario del recurso sobre quién puede cargar un recurso.

El encabezado Cross-Origin-Resource-Policy acepta tres valores posibles:

Cross-Origin-Resource-Policy: same-site

Los recursos marcados como same-site solo se pueden cargar desde el mismo sitio.

Cross-Origin-Resource-Policy: same-origin

Los recursos marcados como same-origin solo se pueden cargar desde el mismo origen.

Cross-Origin-Resource-Policy: cross-origin

Los recursos marcados como cross-origin se pueden cargar en cualquier sitio web. (Este valor se agregó a la especificación de CORP junto con el COEP).

Política de abridor de origen cruzado

La Política de abridor de origen cruzado (COOP) te permite garantizar que una ventana de nivel superior esté aislada de otros documentos colocándola en un grupo de contexto de navegación diferente para que no pueda interactuar directamente con la ventana de nivel superior. Por ejemplo, si un documento con COOP abre una ventana emergente, su propiedad window.opener será null. Además, la propiedad .closed de la referencia al abridor mostrará true.

COOP

El encabezado Cross-Origin-Opener-Policy acepta tres valores posibles:

Cross-Origin-Opener-Policy: same-origin

Los documentos marcados como same-origin pueden compartir el mismo grupo de contexto de navegación con documentos del mismo origen que también estén marcados explícitamente como same-origin.

COOP

Cross-Origin-Opener-Policy: same-origin-allow-popups

Un documento de nivel superior con same-origin-allow-popups conserva las referencias a cualquiera de sus ventanas emergentes que no establecen COOP o que inhabilitan el aislamiento estableciendo una COOP de unsafe-none.

COOP

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none es la opción predeterminada y permite que el documento se agregue al grupo de contexto de navegación del usuario que abre, a menos que este tenga un COOP de same-origin.

Resumen

Si deseas tener acceso garantizado a funciones potentes como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() o temporizadores de alta resolución con mayor precisión, recuerda que tu documento debe usar COEP con el valor require-corp y COOP con el valor same-origin. Si no se usan, el navegador no garantizará un aislamiento suficiente para habilitar de manera segura esas funciones potentes. Para determinar la situación de tu página, verifica si self.crossOriginIsolated muestra true.

Descubre los pasos para implementar esto en Cómo hacer que tu sitio web esté "aislado" en orígenes cruzados con COOP y COEP.

Recursos