Isolamento de sites para desenvolvedores da Web

O Chrome 67 no computador tem um novo recurso chamado Isolamento de sites ativado por padrão. Isso explica do que se trata o isolamento de sites, por que ele é necessário e por que os desenvolvedores da Web deveriam esteja ciente disso.

O que é o isolamento de sites?

A Internet é destinada a assistir vídeos de gatos e gerenciar carteiras de criptomoedas, entre outras coisas — mas você não quer que fluffycats.example tenha acesso às suas criptomoedas preciosas. Felizmente, normalmente, os sites não podem acessar os dados uns dos outros dentro do navegador, graças à API Same-Origin Política Ainda assim, sites maliciosos podem tentar burlar essa política para atacar outros sites, e às vezes, bugs de segurança são encontrados no código do navegador que aplica a política de mesma origem. A A equipe do Chrome pretende corrigir esses bugs o mais rápido possível.

O isolamento de sites é um recurso de segurança do Chrome que oferece uma linha de defesa adicional para com menor probabilidade de sucesso desses ataques. Ele garante que as páginas de diferentes sites sejam sempre colocadas em processos diferentes, cada um executado em uma sandbox que limita o que o processo pode fazer. Essa limitação também impede que o processo receba determinados tipos de dados sensíveis de outros sites. Como resultado. Com o isolamento de sites, é muito mais difícil que sites maliciosos usem ataques de canal lateral, como Spectre, para roubar dados de outros sites. Quando a equipe do Chrome terminar restrições adicionais, o isolamento de sites também será útil mesmo quando a página de um invasor puder causar falhas das regras no próprio processo.

Com o isolamento de sites, fica mais difícil para sites não confiáveis acessarem ou roubarem informações. das suas contas em outros sites. Ele oferece proteção adicional contra vários tipos de bugs de segurança, como os recentes ataques de canal lateral Meltdown e Spectre.

Para mais detalhes sobre o isolamento de sites, acesse nosso artigo no blog de segurança do Google (em inglês).

Bloqueio de leitura de origem cruzada

Mesmo quando todas as páginas entre sites são colocadas em processos separados, as páginas ainda podem solicitar legitimamente alguns sub-recursos entre sites, como imagens e JavaScript. Uma página da Web maliciosa pode usar <img> para carregar um arquivo JSON com dados sensíveis, como seu saldo bancário:

<img src="https://your-bank.example/balance.json" />
<!-- Note: the attacker refused to add an `alt` attribute, for extra evil points. -->

Sem o isolamento de sites, o conteúdo do arquivo JSON seria armazenado na memória do renderizador , e o renderizador percebe que não é um formato de imagem válido e não renderiza uma imagem. Mas o invasor poderia explorar uma vulnerabilidade como o Spectre para potencialmente ler essa com um pedaço de memória.

Em vez de usar <img>, o invasor também pode usar <script> para comprometer os dados sensíveis com memória:

<script src="https://your-bank.example/balance.json"></script>

O bloqueio de leitura de origem cruzada (CORB, na sigla em inglês) é um novo recurso de segurança que impede o conteúdo de balance.json de entrar na memória do renderizador de processo com base no tipo MIME.

Vamos analisar como a CORB funciona. Um site pode solicitar dois tipos de recursos de um servidor:

  1. recursos de dados, como documentos HTML, XML ou JSON
  2. recursos de mídia, como imagens, JavaScript, CSS ou fontes

Um site pode receber recursos de dados da própria origem ou de outras origens com cabeçalhos CORS permissivos, como Access-Control-Allow-Origin: *. Por outro lado, recursos de mídia podem ser incluídos de qualquer origem, mesmo sem cabeçalhos CORS permissivos.

O CORB impede que o processo do renderizador receba um recurso de dados de origem cruzada (por exemplo, HTML, XML ou JSON) se:

  • o recurso tem um cabeçalho X-Content-Type-Options: nosniff;
  • O CORS não permite explicitamente o acesso ao recurso

Se o recurso de dados de origem cruzada não tiver o cabeçalho X-Content-Type-Options: nosniff definido, O CORB tenta detectar o corpo da resposta para determinar se é HTML, XML ou JSON. Isso é necessário porque alguns servidores da Web estão configurados incorretamente e exibem imagens como text/html, por exemplo.

Os recursos de dados bloqueados pela política do CORB são apresentados ao processo como vazios, embora ela ainda ocorre em segundo plano. Por isso, uma página da Web maliciosa tem dificuldade ou seja, extrair dados entre sites no processo para roubar.

Para ter a melhor segurança e aproveitar os benefícios do CORB, recomendamos o seguinte:

  • Marque as respostas com o cabeçalho Content-Type correto. Por exemplo, os recursos HTML devem ser disponibilizados como text/html, os recursos JSON com um tipo JSON MIME e recursos XML com um tipo XML MIME).
  • Desative a detecção usando o cabeçalho X-Content-Type-Options: nosniff. Sem esse cabeçalho, O Chrome faz uma rápida análise de conteúdo para tentar confirmar se o tipo está correto, mas como esse prefere permitir respostas para evitar o bloqueio de itens como arquivos JavaScript, é melhor fazer a coisa certa por conta própria.

Para mais detalhes, consulte a Artigo do CORB para desenvolvedores Web ou explicação detalhada do CORB (em inglês).

Por que os desenvolvedores Web devem se preocupar com o isolamento de sites?

Em sua maioria, o isolamento de sites é um recurso do navegador que não é diretamente expostos a desenvolvedores Web. Por exemplo, não há nova API exposta à Web para aprender. Em geral, a Web as páginas não devem ser capazes de distinguir a diferença ao serem exibidas com ou sem o isolamento de sites.

No entanto, existem algumas exceções a essa regra. Para ativar o isolamento de sites, há algumas etapas que podem afetar seu site. Mantemos uma lista de problemas conhecidos de isolamento de sites; e detalhamos os mais importantes abaixo.

O layout de página inteira não é mais síncrono

Com o isolamento de sites, não há mais garantia de que o layout de página inteira seja síncrono, uma vez que os frames do uma página agora pode ser distribuída em vários processos. Isso pode afetar as páginas se elas presumirem que um a mudança de layout se propaga imediatamente para todos os frames da página.

Como exemplo, vamos considerar um site chamado fluffykittens.example que se comunica com uma widget de rede social hospedado em social-widget.example:

<!-- https://fluffykittens.example/ -->
<iframe src="https://social-widget.example/" width="123"></iframe>
<script>
  const iframe = document.querySelector('iframe');
  iframe.width = 456;
  iframe.contentWindow.postMessage(
    // The message to send:
    'Meow!',
    // The target origin:
    'https://social-widget.example'
  );
</script>

Inicialmente, a largura da <iframe> do widget social é de 123 pixels. Mas a página do FluffyKittens muda a largura para 456 pixels (acionando o layout) e envia uma mensagem para o widget de rede social, que tem o seguinte código:

<!-- https://social-widget.example/ -->
<script>
  self.onmessage = () => {
    console.log(document.documentElement.clientWidth);
  };
</script>

Sempre que o widget social recebe uma mensagem pela API postMessage, ele registra a largura de seu elemento <html> raiz.

Qual valor de largura é registrado? Antes de o Chrome ativar o isolamento de sites, a resposta era 456. Acesso document.documentElement.clientWidth força o layout, que costumava ser síncrono antes do Chrome o isolamento de sites. No entanto, com o isolamento de sites ativado, o widget de redes sociais de origem cruzada o novo layout agora acontece de forma assíncrona em um processo separado. Dessa forma, a resposta agora também pode ser 123, ou seja, o valor antigo de width.

Se uma página mudar o tamanho de um <iframe> de origem cruzada e enviar um postMessage para ela com Isolamento de site: o frame de destino ainda não sabe o novo tamanho ao receber a mensagem. Mais em geral, isso pode causar falhas nas páginas se elas presumirem que uma mudança de layout é propagada imediatamente para todos frames na página.

Nesse exemplo específico, uma solução mais robusta definiria width no frame pai e detectar essa mudança no <iframe> detectando um evento resize.

Gerenciadores de descarregamento podem expirar com mais frequência

Quando um frame navega ou fecha, o documento antigo e todos os subframes incorporados nele executam o gerenciador unload. Se a nova navegação ocorre no mesmo processo do renderizador (por exemplo, para uma navegação de mesma origem), os gerenciadores unload do documento antigo e dos subframes dele podem ser executados para muito tempo antes de permitir o commit da nova navegação.

addEventListener('unload', () => {
  doSomethingThatMightTakeALongTime();
});

Nessa situação, os gerenciadores unload em todos os frames são muito confiáveis.

No entanto, mesmo sem o isolamento de sites, algumas navegações do frame principal são em processo cruzado, o que afeta descarregamento do gerenciador. Por exemplo, se você navegar de old.example para new.example digitando o URL na barra de endereço, a navegação pelo new.example acontece em um novo processo. O comando de descarregamento gerenciadores de old.example e os subframes deles são executados no processo old.example em segundo plano. depois que a página new.example for mostrada, e os gerenciadores de descarregamento antigos serão encerrados terminar dentro de um determinado tempo limite. Como os gerenciadores de descarregamento podem não terminar antes do tempo limite, o comportamento de descarregamento é menos confiável.

Com o isolamento de sites, todas as navegações entre sites se tornam processos cruzados, de modo que os documentos de sites diferentes não compartilham um processo entre si. Como resultado, a situação acima se aplica mais casos, e descarregamento de gerenciadores em <iframe>s geralmente têm os comportamentos em segundo plano e tempo limite. descritas acima.

Outra diferença resultante do isolamento de sites é a nova ordem paralela de gerenciadores de descarregamento: sem o isolamento de sites, os gerenciadores de descarregamento são executados em uma ordem estrita de cima para baixo nos frames. Mas com o Site Os gerenciadores de isolamento e descarregamento são executados em paralelo em diferentes processos.

Estas são as principais consequências da ativação do isolamento de sites. A equipe do Chrome está trabalhando melhorando a confiabilidade dos gerenciadores de descarregamento para casos de uso comuns, quando possível. Também estamos cientes de bugs em que os gerenciadores de descarregamento de subframes ainda não conseguem utilizar determinados recursos e estão trabalhando para resolvê-los.

Um caso importante para gerenciadores de descarregamento é enviar pings de final da sessão. Isso é comumente feito da seguinte forma:

addEventListener('pagehide', () => {
  const image = new Image();
  img.src = '/end-of-session';
});

Uma abordagem melhor e mais robusta considerando essa mudança é usar navigator.sendBeacon. como alternativa:

addEventListener('pagehide', () => {
  navigator.sendBeacon('/end-of-session');
});

Se você precisar de mais controle sobre a solicitação, use a opção keepalive da API Fetch:

addEventListener('pagehide', () => {
  fetch('/end-of-session', {keepalive: true});
});

Conclusão

Com o isolamento de sites, fica mais difícil para sites não confiáveis acessarem ou roubarem informações dos seus contas em outros sites isolando cada site em um processo próprio. Como parte disso, o CORB tenta para manter os recursos de dados sensíveis fora do processo do renderizador. Nossas recomendações acima garantem que você aproveitar ao máximo esses novos recursos de segurança.

Agradecimentos a Alex Moshchuk, Charlie Reis, Jason Miller, Nasko Oskov, Philip Walton, Shubhie Panicker e Thomas steiner por ler uma versão de rascunho deste artigo e dar seu feedback.