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

Publicado em 4 de maio de 2020

Em Como tornar seu site com isolamento de origem cruzada usando COOP e COEP explicamos como adotar o estado com isolamento de origem cruzada usando COOP e COEP. Este é um artigo complementar que explica por que o isolamento entre origens é necessário para ativar recursos avançados no navegador.

Glossário

Este documento usa muitos termos abreviados e com nomes semelhantes. Para esclarecer, criamos um miniglossário:

Contexto

A Web é criada com base 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 entre origens. Por exemplo, um documento de https://a.example é impedido de 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 entre origens, como imagens ou scripts
  • Abrir janelas de diálogo entre origens com uma referência DOM

Quando a comunidade da Web percebeu os benefícios de uma política de mesma origem estrita, a Web já dependia dessas exceções.

Os efeitos colaterais de segurança de uma política de mesma origem tão flexível foram corrigidos de duas maneiras:

  • O protocolo de compartilhamento de recursos entre origens (CORS) garante que o servidor permita o compartilhamento de um recurso com uma determinada origem.
  • Os desenvolvedores removem implicitamente o acesso direto de script a recursos entre origens, preservando a compatibilidade com versões anteriores. Esses recursos entre origens são chamados de recursos "opacos". É por isso que a manipulação de pixels entre origens com 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.

O grupo de contexto de navegação inclui o site principal e os recursos do site incorporado.

Por muito tempo, essa combinação foi suficiente para manter os navegadores seguros, com casos extremos limitados que precisavam de correção direta (como vulnerabilidades JSON).

Isso mudou com Spectre, que torna potencialmente legíveis todos os dados carregados no mesmo grupo de contexto de navegação que o código. Ao medir o tempo que determinadas operações levam, os invasores podem adivinhar o conteúdo dos caches da CPU e, portanto, o conteúdo da memória do processo. Esses ataques são possíveis com timers de baixa granularidade que existem na plataforma e podem ser acelerados com timers de alta granularidade, explícitos (como performance.now()) e implícitos (como SharedArrayBuffers).

Se evil.com incorporar uma imagem entre origens, ele poderá usar um ataque Spectre para ler os dados de pixel da imagem incorporada. Isso torna as proteções que dependem da "opacidade" ineficazes.

Evil.com é o site principal, que ataca o iframe e as imagens incorporados de b.example usando o Spectre.

O ideal é que todas as solicitações entre origens sejam analisadas pelo servidor que possui o recurso. Se a análise não for realizada, os dados nunca deverão chegar ao grupo de contexto de navegação de um ator mal-intencionado. Assim, os dados ficam fora do alcance de possíveis ataques Spectre. Chamamos isso de estado de isolamento de origem cruzada.

Quando o código incorporado está em um estado de isolamento de origem cruzada, o site solicitante é considerado menos perigoso. Isso permite que o site solicitante use SharedArrayBuffer, performance.measureUserAgentSpecificMemory() e timers de alta resolução com melhor precisão, evitando possíveis ataques Spectre. Esse estado também impede a modificação de document.domain.

Política de incorporador entre origens

A Política de incorporador entre origens (COEP) impede que um documento carregue recursos entre origens que não concedam permissão explicitamente ao documento com CORP ou CORS. Com esse recurso, é possível declarar que um documento não pode carregar esses recursos.

Um diagrama de quais recursos incorporados são permitidos e não permitidos, graças às políticas de CORP.
O site pai, a.example, definiu a política COEP como require-corp. a.example quer incorporar três recursos de b.example, mas apenas dois são bem-sucedidos. As duas incorporações bem-sucedidas incluem um arquivo JavaScript com uma política CORP entre origens e uma imagem com CORS permitido. O terceiro recurso é um vídeo que tem uma política CORP que exige que o recurso seja incorporado apenas na mesma origem. Portanto, o vídeo não será carregado em a.example.

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

Cross-Origin-Embedder-Policy: require-corp

O COEP usa um único valor de require-corp. Isso aplica a política de que o documento só pode carregar recursos da mesma origem ou recursos marcados explicitamente 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 entre origens oferece suporte ao compartilhamento de recursos entre origens (CORS), você pode usar o crossorigin atributo para carregá-lo na sua 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 veiculado com cabeçalhos CORS, use o crossorigin atributo para que a solicitação de busca do recurso use CORS modo. Isso também impede que a imagem seja carregada, a menos que ela defina cabeçalhos CORS.

Da mesma forma, é possível buscar dados entre origens usando o método fetch(), que não exige tratamento 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) 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 aceita 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 junto com o COEP.)

Política de abertura entre origens

A Política de abertura entre origens (COOP) permite isolar uma janela de nível superior de outros documentos, colocando os documentos em um grupo de contexto de navegação separado. Dessa forma, os documentos não podem interagir diretamente com a janela de nível superior. Por exemplo, se um documento com COOP abrir uma caixa de diálogo, a propriedade window.opener será null. A propriedade .closed da referência do abridor é true.

a.example não pôde abrir b.example em uma caixa de diálogo.

O cabeçalho Cross-Origin-Opener-Policy aceita 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 estão marcados explicitamente como same-origin.

Desenho representando uma janela capaz de interagir com um pop-up de mesma origem que está no mesmo grupo de contexto de navegação, mas não um rotulado como &quot;mesma origem&quot; enquanto ainda está fora do grupo de contexto de navegação.

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

Um documento de nível superior com same-origin-allow-popups mantém referências a todos os pop-ups que não definem o 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 acessar recursos como SharedArrayBuffer, performance.measureUserAgentSpecificMemory(), ou timers de alta resolução com melhor precisão, seu documento precisará usar o COEP com o valor de require-corp e o COOP com o valor de same-origin. Na ausência de um deles, o navegador não vai garantir isolamento suficiente para ativar esses recursos avançados com segurança. Você pode determinar a situação da sua página verificando se self.crossOriginIsolated retorna true.

Saiba como implementar isso em Como tornar seu site "isolado entre origens" usando COOP e COEP.

Recursos