Por que você precisa do "isolamento de origem cruzada" para recursos avançados

Saiba por que o isolamento de origem cruzada é necessário para usar recursos avançados, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() e o timer de alta resolução com maior precisão.

Domenic Denicola
Domenic Denicola

Introdução

Em Como tornar seu site "isolado de origem cruzada" usando COOP e COEP, explicamos como adotar o estado "isolado de origem cruzada" usando COOP e COEP. Este é um artigo complementar que explica por que o isolamento de origem cruzada é necessário para ativar recursos poderosos no navegador.

Contexto

A Web é baseada na política de mesma origem: um recurso de segurança que restringe como documentos e scripts podem interagir com recursos de outra origem. Esse princípio restringe as maneiras como os sites podem acessar recursos de origem cruzada. Por exemplo, um documento de https://a.example não pode acessar dados hospedados em https://b.example.

No entanto, a política de mesma origem teve algumas exceções históricas. Qualquer site pode:

  • Incorporar iframes entre origens
  • Incluir recursos de várias origens, como imagens ou scripts
  • Abrir janelas pop-up de origem cruzada com uma referência DOM

Se a Web pudesse ser projetada do zero, essas exceções não existiriam. Infelizmente, quando a comunidade da Web percebeu os principais benefícios de uma política rígida de mesma origem, a Web já estava dependendo dessas exceções.

Os efeitos colaterais de segurança de uma política de mesma origem frouxa foram corrigidos de duas maneiras. Uma delas foi a introdução de um novo protocolo chamado Compartilhamento de recursos entre origens (CORS), cuja finalidade é garantir que o servidor permita o compartilhamento de um recurso com uma origem específica. A outra maneira é removendo implicitamente o acesso direto do script a recursos de origem cruzada, preservando a compatibilidade com versões anteriores. Esses recursos de origem cruzada são chamados de recursos "opacos". Por exemplo, é por isso que manipular os pixels de uma imagem de origem cruzada usando CanvasRenderingContext2D falha, a menos que o CORS seja aplicado à imagem.

Todas essas decisões de política estão acontecendo em um grupo de contexto de navegação.

Grupo de contexto de navegação

Por muito tempo, a combinação de CORS e recursos opacos foi suficiente para proteger os navegadores. Às vezes, casos extremos (como vulnerabilidades do JSON) foram descobertos e precisavam ser corrigidos, mas, no geral, o princípio de não permitir acesso de leitura direto aos bytes brutos de recursos de várias origens foi bem-sucedido.

Isso mudou com o Spectre, que torna todos os dados carregados para o mesmo grupo de contexto de navegação do seu código potencialmente legíveis. Ao medir o tempo que determinadas operações levam, os invasores podem adivinhar o conteúdo dos caches da CPU e, com isso, o conteúdo da memória do processo. Esses ataques de tempo são possíveis com timers de baixa granularidade que existem na plataforma, mas podem ser acelerados com timers de alta granularidade, tanto explícitos (como performance.now()) quanto implícitos (como SharedArrayBuffers). Se o evil.com incorporar uma imagem de origem cruzada, ele poderá usar um ataque Spectre para ler os dados de pixel, o que torna as proteções que dependem de "opacidade" ineficazes.

Spectr

O ideal é que todas as solicitações entre origens sejam verificadas explicitamente pelo servidor que é proprietário do recurso. Se a verificação não for fornecida pelo servidor proprietário do recurso, os dados nunca vão entrar no grupo de contexto de navegação de um agente malicioso e, portanto, vão ficar fora do alcance de qualquer ataque Spectre que uma página da Web possa realizar. Chamamos isso de estado isolado entre origens. É exatamente isso que o COOP+COEP significa.

Em um estado isolado entre origens, o site solicitante é considerado menos perigoso e isso desbloqueia recursos poderosos, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() e timers de alta resolução, com maior precisão, que poderiam ser usados para ataques do tipo Spectre. Ele também impede a modificação de document.domain.

Política de incorporador entre origens

A política de inserção de origem cruzada (COEP) impede que um documento carregue recursos de origem cruzada que não concedem explicitamente a permissão do documento (usando CORP ou CORS). Com esse recurso, é possível declarar que um documento não pode carregar esses recursos.

Como a COEP funciona

Para ativar essa política, anexe o seguinte cabeçalho HTTP ao documento:

Cross-Origin-Embedder-Policy: require-corp

A palavra-chave require-corp é o único valor aceito para COEP. Isso reforça a política de que o documento só pode carregar recursos da mesma origem ou recursos explicitamente marcados como carregáveis de outra origem.

Para que os recursos possam ser carregados de outra origem, eles precisam oferecer suporte ao Compartilhamento de recursos entre origens (CORS) ou à política de recursos entre origens (CORP).

Compartilhamento de recursos entre origens

Se um recurso de origem cruzada oferecer suporte ao Compartilhamento de recursos entre origens (CORS), use o atributo crossorigin para carregá-lo na página da Web sem ser bloqueado pelo COEP.

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

Por exemplo, se esse recurso de imagem for enviado com cabeçalhos CORS, use o atributo crossorigin para que a solicitação de busca do recurso use o modo CORS. Isso também impede que a imagem seja carregada, a menos que defina cabeçalhos CORS.

Da mesma forma, é possível buscar dados de várias origens pelo método fetch(), que não requer um processamento especial, desde que o servidor responda com os cabeçalhos HTTP corretos.

Política de recursos entre origens

A política de recursos entre origens (CORP, na sigla em inglês) foi originalmente introduzida como uma opção para proteger seus recursos contra o carregamento por outra origem. No contexto do COEP, o CORP pode especificar a política do proprietário do recurso para quem pode carregar um recurso.

O cabeçalho Cross-Origin-Resource-Policy tem três valores possíveis:

Cross-Origin-Resource-Policy: same-site

Os recursos marcados como same-site só podem ser carregados do mesmo site.

Cross-Origin-Resource-Policy: same-origin

Os recursos marcados como same-origin só podem ser carregados da mesma origem.

Cross-Origin-Resource-Policy: cross-origin

Os recursos marcados como cross-origin podem ser carregados por qualquer site. Esse valor foi adicionado à especificação CORP com a COEP.

Política de abertura entre origens

A política de abertura de origem cruzada (COOP, na sigla em inglês) permite que você isole uma janela de nível superior de outros documentos, colocando-os em um grupo de contexto de navegação diferente para que não possam interagir diretamente com a janela de nível superior. Por exemplo, se um documento com COOP abrir um pop-up, a propriedade window.opener dele será null. Além disso, a propriedade .closed da referência do abridor a ele vai retornar true.

COOP

O cabeçalho Cross-Origin-Opener-Policy tem três valores possíveis:

Cross-Origin-Opener-Policy: same-origin

Os documentos marcados como same-origin podem compartilhar o mesmo grupo de contexto de navegação com documentos de mesma origem que também são marcados explicitamente como same-origin.

COOP

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

Um documento de nível superior com same-origin-allow-popups retém referências a qualquer dos pop-ups que não definem COOP ou que desativam o isolamento definindo um COOP de unsafe-none.

COOP

Cross-Origin-Opener-Policy: unsafe-none

unsafe-none é o padrão e permite que o documento seja adicionado ao grupo de contexto de navegação do abridor, a menos que o próprio abridor tenha um COOP de same-origin.

Resumo

Se você quiser acesso garantido a recursos poderosos, como SharedArrayBuffer, performance.measureUserAgentSpecificMemory() ou timers de alta resolução com maior precisão, lembre-se de que o documento precisa usar o COEP com o valor de require-corp e o COOP com o valor de same-origin. Na ausência de qualquer um deles, o navegador não garante isolamento suficiente para ativar esses recursos com segurança. É possível determinar a situação da sua página verificando se self.crossOriginIsolated retorna true.

Saiba como implementar isso em Como tornar seu site "isolado de origem cruzada" usando COOP e COEP.

Recursos