Hosting sicuro dei dati utente nelle moderne applicazioni web

David Dworken
David Dworken

Molte applicazioni web devono mostrare contenuti controllati dagli utenti. Può trattarsi di operazioni semplici come la pubblicazione di immagini caricate dagli utenti (ad esempio, foto del profilo) o complesse come la visualizzazione di codice HTML controllato dall'utente (ad esempio, un tutorial sullo sviluppo web). È sempre stato difficile farlo in sicurezza, quindi ci siamo impegnati per trovare soluzioni semplici ma sicure che possano essere applicate alla maggior parte dei tipi di applicazioni web.

Soluzioni classiche per l'isolamento dei contenuti non attendibili

La soluzione classica per pubblicare in modo sicuro contenuti controllati dagli utenti consiste nell'utilizzare i cosiddetti domini sandbox. L'idea di base è che se il dominio principale della tua applicazione è example.com, potresti pubblicare tutti i contenuti non attendibili su exampleusercontent.com. Poiché questi due domini sono cross-site, qualsiasi contenuto dannoso su exampleusercontent.com non può influire su example.com.
Questo approccio può essere usato per pubblicare in sicurezza tutti i tipi di contenuti non attendibili, tra cui immagini, download e HTML. Potrebbe non sembrare necessario utilizzare questa funzionalità per le immagini o i download, ma ciò consente di evitare i rischi dello sniffing dei contenuti, soprattutto nei browser precedenti.
I domini sandbox sono ampiamente utilizzati in tutto il settore e hanno funzionato bene da molto tempo. Tuttavia, presentano due principali svantaggi:

  • Spesso le applicazioni devono limitare l'accesso ai contenuti a un singolo utente, il che richiede l'implementazione dell'autenticazione e dell'autorizzazione. Poiché i domini sandbox non condividono intenzionalmente i cookie con il dominio principale dell'applicazione, questa operazione è molto difficile da eseguire in sicurezza. Per supportare l'autenticazione, i siti devono fare affidamento su URL di funzionalità oppure impostare cookie di autenticazione separati per il dominio sandbox. Questo secondo metodo è particolarmente problematico nel web moderno, dove molti browser limitano i cookie in più siti per impostazione predefinita.
  • Sebbene i contenuti degli utenti siano isolati dal sito principale, non vengono isolati da altri contenuti dell'utente. Ciò comporta il rischio che contenuti utente dannosi attaccano altri dati sul dominio sandbox (ad esempio, tramite la lettura di dati della stessa origine).

Vale anche la pena notare che i domini sandbox aiutano a mitigare i rischi di phishing poiché le risorse sono chiaramente segmentate su un dominio isolato.

Soluzioni moderne per la pubblicazione di contenuti per gli utenti

Nel corso del tempo il web si è evoluto e ora esistono modi più semplici e sicuri per pubblicare contenuti non attendibili. Ci sono molti approcci diversi in questo caso, quindi definiremo due soluzioni che sono attualmente ampiamente utilizzate in Google.

Approccio 1: pubblicazione di contenuti di utenti inattivi

Se un sito deve pubblicare solo contenuti di utenti inattivi (ovvero contenuti non HTML o JavaScript, ad esempio immagini e download), ora puoi farlo senza un dominio sandbox isolato. Ci sono due passaggi chiave:

  • Imposta sempre l'intestazione Content-Type su un tipo MIME noto che è supportato da tutti i browser e che non contiene contenuti attivi (in caso di dubbi, application/octet-stream è una scelta sicura).
  • Inoltre, imposta sempre le seguenti intestazioni della risposta per garantire che il browser isoli completamente la risposta.
Intestazione della risposta Purpose

X-Content-Type-Options: nosniff

Impedisce lo sniffing dei contenuti

Content-Disposition: attachment; filename="download"

Attiva un download anziché il rendering

Content-Security-Policy: sandbox

Archivia i contenuti come se fossero pubblicati su un dominio separato

Content-Security-Policy: default-src ‘none'

Disabilita l'esecuzione di JavaScript (e l'inclusione di eventuali risorse secondarie)

Cross-Origin-Resource-Policy: same-site

Impedisce l'inclusione della pagina tra siti

Questa combinazione di intestazioni garantisce che la risposta possa essere caricata solo come sottorisorsa dall'applicazione o scaricata come file dall'utente. Inoltre, le intestazioni forniscono più livelli di protezione contro i bug del browser tramite l'intestazione sandbox CSP e la restrizione default-src. Nel complesso, la configurazione descritta sopra fornisce un alto grado di certezza che le risposte fornite in questo modo non possono portare a vulnerabilità di iniezione o isolamento.

Difesa in profondità

Sebbene la soluzione di cui sopra rappresenti in genere una difesa sufficiente contro l’XSS, ci sono una serie di misure di protezione aggiuntive che puoi applicare per fornire ulteriori livelli di sicurezza:

  • Imposta un'intestazione X-Content-Security-Policy: sandbox per garantire la compatibilità con IE11.
  • Imposta un'intestazione Content-Security-Policy: frame-ancestors 'none' per bloccare l'incorporamento dell'endpoint.
  • Sandbox dei contenuti degli utenti in un sottodominio isolato per:
    • Pubblicazione di contenuti degli utenti in un sottodominio isolato (ad esempio, Google utilizza domini come product.usercontent.google.com).
    • Imposta Cross-Origin-Opener-Policy: same-origin e Cross-Origin-Embedder-Policy: require-corp per attivare l'isolamento multiorigine.

Approccio 2: pubblicazione di contenuti di utenti attivi

La pubblicazione sicura dei contenuti attivi (ad esempio, immagini HTML o SVG) può avvenire anche senza i punti deboli dell'approccio classico ai domini sandbox.
L'opzione più semplice consiste nello utilizzare l'intestazione Content-Security-Policy: sandbox per indicare al browser di isolare la risposta. Sebbene non tutti i browser web implementino l'isolamento dei processi per i documenti sandbox, è probabile che i continui perfezionamenti ai modelli di processo del browser migliorino la separazione dei contenuti sandbox dall'incorporamento delle applicazioni. Se gli attacchi SpectreJS e compromissioni del rendering sono al di fuori del tuo modello di minaccia, l'utilizzo della sandbox CSP è probabilmente una soluzione sufficiente.
Google ha sviluppato una soluzione in grado di isolare completamente i contenuti attivi non attendibili mediante la modernizzazione del concetto di domini sandbox. L'idea alla base è:

  • Crea un nuovo dominio sandbox da aggiungere all'elenco dei suffissi pubblici. Ad esempio, aggiungendo exampleusercontent.com al PSL, puoi assicurarti che foo.exampleusercontent.com e bar.exampleusercontent.com siano in più siti e quindi completamente isolati tra loro.
  • Gli URL che corrispondono a *.exampleusercontent.com/shim vengono tutti indirizzati a un file shim statico. Questo file shim contiene un breve snippet HTML e JavaScript che ascolta il gestore di eventi message e esegue il rendering di tutti i contenuti ricevuti.
  • Per usarlo, il prodotto crea un iframe o un popup per $RANDOM_VALUE.exampleusercontent.com/shim e utilizza postMessage per inviare i contenuti non attendibili allo shim per il rendering.
  • I contenuti visualizzati vengono trasformati in un BLOB e visualizzati all'interno di un iframe con sandbox.

Rispetto all'approccio classico ai domini sandbox, questo assicura che tutti i contenuti siano completamente isolati su un unico sito. Inoltre, avendo l'applicazione principale che deve recuperare i dati di cui eseguire il rendering, non è più necessario usare gli URL delle funzionalità.

Conclusione

Insieme, queste due soluzioni consentono di migrare dai domini sandbox classici come googleusercontent.com a soluzioni più sicure compatibili con il blocco dei cookie di terze parti. Noi di Google abbiamo già eseguito la migrazione di molti prodotti a queste soluzioni e abbiamo in programma altre migrazioni per il prossimo anno.