Isolamento dei siti per sviluppatori web

Chrome 67 per computer ha una nuova funzionalità chiamata Isolamento dei siti attiva per impostazione predefinita. Questo articolo spiega che cos'è l'isolamento dei siti, perché è necessario e perché gli sviluppatori web dovrebbero esserne a conoscenza.

Che cos'è l'isolamento dei siti?

Internet è utile per guardare video di gatti e gestire i portafogli di criptovalute, tra le altre cose, ma non vorresti che fluffycats.example avesse accesso alle tue preziose criptomonete. Fortunatamente, solitamente i siti web non possono accedere ai dati l'uno dell'altro all'interno del browser grazie al principio di origine stessa. Tuttavia, i siti web dannosi potrebbero tentare di aggirare questo criterio per attaccare altri siti web e, occasionalmente, vengono rilevati bug di sicurezza nel codice del browser che applica il criterio della stessa origine. Il team di Chrome si impegna a correggere questi bug il più rapidamente possibile.

L'isolamento dei siti è una funzionalità di sicurezza di Chrome che offre una linea di difesa aggiuntiva per ridurre le probabilità di successo di questi attacchi. Garantisce che le pagine di siti web diversi vengano sempre inserite in processi diversi, ognuno in esecuzione in una sandbox che limita le attività consentite al processo. Inoltre, impedisce al processo di ricevere determinati tipi di dati sensibili da altri siti. Di conseguenza, con l'isolamento dei siti è molto più difficile per un sito web dannoso utilizzare attacchi speculativi lato canale come Spectre per rubare dati da altri siti. Man mano che il team di Chrome completa altre applicazioni, l'isolamento dei siti sarà utile anche quando la pagina di un malintenzionato può violare alcune delle regole nel proprio processo.

L'isolamento dei siti rende più difficile per i siti web non attendibili accedere o rubare informazioni dai tuoi account su altri siti web. Offre una protezione aggiuntiva contro vari tipi di bug di sicurezza, come i recenti attacchi lato canale di Meltdown e Spectre.

Per ulteriori dettagli sull'isolamento dei siti, leggi il nostro articolo sul blog Google Security.

Blocco della lettura interorigine

Anche quando tutte le pagine cross-site vengono inserite in processi separati, le pagine possono comunque richiedere legittimamente alcune risorse secondarie cross-site, come immagini e JavaScript. Una pagina web dannosa potrebbe utilizzare un elemento <img> per caricare un file JSON con dati sensibili, come il saldo bancario:

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

Senza l'isolamento dei siti, i contenuti del file JSON arriverebbero nella memoria del processo del visualizzatore, che a quel punto nota che non si tratta di un formato di immagine valido e non la visualizza. Tuttavia, l'utente malintenzionato potrebbe sfruttare una vulnerabilità come Spectre per leggere potenzialmente quel frammento di memoria.

Anziché utilizzare <img>, l'attaccante potrebbe utilizzare anche <script> per eseguire il commit dei dati sensibili nella memoria:

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

Il blocco della lettura interorigine (CORB) è una nuova funzionalità di sicurezza che impedisce ai contenuti dibalance.json di entrare nella memoria del processo di rendering in base al tipo MIME.

Vediamo come funziona CORB. Un sito web può richiedere due tipi di risorse da un server:

  1. risorse di dati come documenti HTML, XML o JSON
  2. Risorse multimediali come immagini, JavaScript, CSS o caratteri

Un sito web è in grado di ricevere risorse di dati dalla propria origine o da altre origini con intestazioni CORS permissive come Access-Control-Allow-Origin: *. D'altra parte, le risorse multimediali possono essere incluse da qualsiasi origine, anche senza intestazioni CORS permissive.

CORB impedisce al processo di rendering di ricevere una risorsa di dati cross-origin (ad es. HTML, XML o JSON) se:

  • La risorsa ha un'intestazione X-Content-Type-Options: nosniff
  • CORS non consente esplicitamente l'accesso alla risorsa

Se la risorsa di dati cross-origin non ha l'intestazione X-Content-Type-Options: nosniff impostata, CORB tenta di analizzare il corpo della risposta per determinare se si tratta di HTML, XML o JSON. Questo è necessario perché alcuni server web sono configurati in modo errato e pubblicano immagini come text/html, ad esempio.

Le risorse di dati bloccate dal criterio CORB vengono presentate al processo come vuote, anche se la richiesta viene comunque eseguita in background. Di conseguenza, una pagina web dannosa ha difficoltà a recuperare i dati cross-site nel suo processo di furto.

Per una sicurezza ottimale e per usufruire di CORB, ti consigliamo quanto segue:

  • Contrassegna le risposte con l'intestazione Content-Type corretta. Ad esempio, le risorse HTML devono essere pubblicate come text/html, le risorse JSON con un tipo MIME JSON e le risorse XML con un tipo MIME XML.
  • Disattivare lo sniffing utilizzando l'intestazione X-Content-Type-Options: nosniff. Senza questa intestazione, Chrome esegue un'analisi rapida dei contenuti per verificare che il tipo sia corretto, ma poiché tende a consentire le risposte per evitare di bloccare elementi come i file JavaScript, è meglio fare la cosa giusta in modo affermativo.

Per maggiori dettagli, consulta l'articolo CORB per gli sviluppatori web o la nostra spiegazione dettagliata di CORB.

Perché l'isolamento dei siti dovrebbe interessare gli sviluppatori web?

Per la maggior parte, l'isolamento dei siti è una funzionalità del browser nascosta che non è direttamente esposta agli sviluppatori web. Ad esempio, non è necessario imparare una nuova API esposta sul web. In generale, le pagine web non dovrebbero essere in grado di distinguere se vengono eseguite con o senza l'isolamento dei siti.

Tuttavia, ci sono alcune eccezioni a questa regola. L'attivazione dell'isolamento dei siti comporta alcuni effetti collaterali sottili che potrebbero influire sul tuo sito web. Gestiamo un elenco di problemi noti relativi all'isolamento dei siti, e di seguito illustriamo i più importanti.

Il layout a pagina intera non è più sincrono

Con l'isolamento dei siti, non è più garantito che il layout a pagina intera sia sincrono, poiché i frame di una pagina ora possono essere distribuiti su più processi. Ciò potrebbe influire sulle pagine se si presume che una modifica del layout si propaghi immediatamente a tutti i frame della pagina.

Ad esempio, prendiamo in considerazione un sito web denominato fluffykittens.example che comunica con un widget social ospitato su 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>

Inizialmente, la larghezza del widget social è pari a 123 pixel.<iframe> Tuttavia, la pagina FluffyKittens modifica la larghezza in 456 pixel (attiva il layout) e invia un messaggio al widget social, che ha il seguente codice:

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

Ogni volta che il widget social riceve un messaggio tramite l'API postMessage, registra la larghezza del suo elemento <html> principale.

Quale valore di larghezza viene registrato? Prima che Chrome attivasse l'isolamento dei siti, la risposta era 456. L'accesso a document.documentElement.clientWidth forza il layout, che in precedenza era sincrono prima dell'attivazione dell'isolamento dei siti da parte di Chrome. Tuttavia, con l'isolamento dei siti abilitato, il nuovo layout del widget social cross-origin ora avviene in modo asincrono in un processo separato. Di conseguenza, ora la risposta può essere anche 123, ovvero il vecchio valore width.

Se una pagina modifica le dimensioni di un <iframe> cross-origin e poi gli invia un postMessage, con la funzionalità Isolamento sito il frame di destinazione potrebbe non conoscere ancora le sue nuove dimensioni al momento della ricezione del messaggio. In generale, questo potrebbe causare il malfunzionamento delle pagine se si presume che una modifica del layout venga propagata immediatamente a tutti i frame della pagina.

In questo caso specifico, una soluzione più solida consisterebbe nell'impostare width nel frame principale e nell'individuare la modifica in <iframe> ascoltando un evento resize.

I gestori di unload potrebbero scadere più spesso

Quando un frame viene visualizzato o chiuso, il vecchio documento e tutti i documenti dei frame secondari incorporati al suo interno eseguono il rispettivo gestore unload. Se la nuova navigazione avviene nello stesso processo di rendering (ad es. per una navigazione nello stesso dominio), gli handler unload del vecchio documento e dei relativi frame secondari possono essere eseguiti per un tempo arbitrariamente lungo prima di consentire l'commit della nuova navigazione.

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

In questa situazione, gli handler unload in tutti i frame sono molto affidabili.

Tuttavia, anche senza l'isolamento dei siti, alcune navigazioni nel frame principale sono cross-process, il che influisce sul comportamento del gestore dell'unload. Ad esempio, se passi da old.example a new.example digitando l'URL nella barra degli indirizzi, la navigazione a new.example avviene in un nuovo processo. I gestori di svuotamento per old.example e i relativi frame secondari vengono eseguiti nel processo old.example in background, dopo la visualizzazione della pagina new.example e i vecchi gestori di svuotamento vengono interrotti se non vengono completati entro un determinato timeout. Poiché i gestori di svuotamento potrebbero non terminare prima del timeout, il comportamento di svuotamento è meno affidabile.

Con l'isolamento dei siti, tutte le navigazioni tra siti diventano tra processi, in modo che i documenti di siti diversi non condividano un processo tra loro. Di conseguenza, la situazione descritta sopra si applica in più casi e i gestori di caricamento in <iframe> hanno spesso i comportamenti in background e di timeout descritti sopra.

Un'altra differenza derivante dall'isolamento dei siti è il nuovo ordinamento parallelo dei gestori di svuotamento: senza l'isolamento dei siti, i gestori di svuotamento vengono eseguiti in un ordine rigoroso dall'alto verso il basso nei frame. Tuttavia, con l'isolamento dei siti, i gestori di svuotamento vengono eseguiti in parallelo in diversi processi.

Queste sono conseguenze fondamentali dell'attivazione dell'isolamento dei siti. Il team di Chrome sta lavorando al miglioramento dell'affidabilità dei gestori di svuotamento per i casi d'uso comuni, ove possibile. Inoltre, siamo consapevoli di bug in cui i gestori di scarico del frame secondario non sono ancora in grado di utilizzare determinate funzionalità e stiamo lavorando per risolverli.

Un caso importante per i gestori di unload è l'invio di ping di fine sessione. Questa operazione viene in genere eseguita come segue:

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

Un approccio migliore e più solido alla luce di questa modifica è utilizzare navigator.sendBeacon instead:

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

Se hai bisogno di un maggiore controllo sulla richiesta, puoi utilizzare l'opzione keepalive dell'API Fetch:

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

Conclusione

L'isolamento dei siti rende più difficile per i siti web non attendibili accedere o rubare informazioni dai tuoi account su altri siti web, isolando ogni sito in un proprio processo. In questo contesto, CORB tenta di mantenere le risorse di dati sensibili al di fuori del processo del visualizzatore. I nostri consigli riportati sopra ti consentono di ottenere il massimo da queste nuove funzionalità di sicurezza.

Grazie a Alex Moshchuk, Charlie Reis, Jason Miller, Nasko Oskov, Philip Walton, Shubhie Panicker e Thomas Steiner per aver letto una versione preliminare di questo articolo e aver fornito il loro feedback.