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 un'operazione semplice come la pubblicazione di immagini caricate dagli utenti (ad esempio, foto del profilo) o di un'operazione complessa come il rendering di codice HTML controllato dagli utenti (ad esempio, un tutorial di sviluppo web). Questa operazione è sempre stata difficile da eseguire in modo sicuro, pertanto abbiamo lavorato per trovare soluzioni semplici, ma sicure, che possano essere applicate alla maggior parte dei tipi di applicazioni web.

Soluzioni classiche per isolare i 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, puoi pubblicare tutti i contenuti non attendibili su exampleusercontent.com. Poiché questi due domini sono cross-site, eventuali contenuti dannosi su exampleusercontent.com non possono influire su example.com. Questo approccio può essere utilizzato per pubblicare in modo sicuro tutti i tipi di contenuti non attendibili, tra cui immagini, download e HTML. Anche se potrebbe non sembrare necessario utilizzarlo per immagini o download, farlo aiuta a evitare i rischi di content sniffing, soprattutto nei browser legacy. I domini sandbox sono ampiamente utilizzati nel settore e funzionano bene da molto tempo. Tuttavia, presentano due svantaggi principali:

  • Le applicazioni spesso 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 dell'applicazione principale, è molto difficile farlo in modo sicuro. Per supportare l'autenticazione, i siti devono fare affidamento sugli URL di funzionalità oppure devono impostare cookie di autenticazione separati per il dominio sandbox. Questo secondo metodo è particolarmente problematico nel web moderno, in cui molti browser limitano i cookie cross-site per impostazione predefinita.
  • Sebbene i contenuti degli utenti siano isolati dal sito principale, non sono isolati da altri contenuti degli utenti. Ciò crea il rischio che il contenuto dell'utente dannoso attacchi altri dati sul dominio sandbox (ad esempio, leggendo dati della stessa origine).

È inoltre importante notare che i domini sandbox contribuiscono a mitigare i rischi di phishing, poiché le risorse sono chiaramente segmentate in un dominio isolato.

Soluzioni moderne per la pubblicazione di contenuti degli utenti

Nel tempo il web si è evoluto e ora esistono modi più semplici e sicuri per erogare contenuti non attendibili. Esistono molti approcci diversi, quindi descriveremo due soluzioni che utilizziamo in Google.

Approccio 1: pubblicazione di contenuti dell'utente inattivo

Se un sito deve pubblicare solo contenuti dell'utente inattivi (ovvero contenuti che non sono HTML o JavaScript, ad esempio immagini e download), ora può farlo in modo sicuro senza un dominio sandbox isolato. Esistono due passaggi chiave:

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

X-Content-Type-Options: nosniff

Impedisce il rilevamento dei contenuti

Content-Disposition: attachment; filename="download"

Attiva un download anziché il rendering

Content-Security-Policy: sandbox

Isola i contenuti come se fossero pubblicati su un dominio separato

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

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

Cross-Origin-Resource-Policy: same-site

Impedisce l'inclusione della pagina tra siti diversi

Questa combinazione di intestazioni garantisce che la risposta possa essere caricata solo come risorsa secondaria 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 limitazione default-src. Nel complesso, la configurazione descritta offre un alto grado di certezza che le risposte fornite in questo modo non possano portare a vulnerabilità di iniezione o isolamento.

Difesa in profondità

Sebbene la soluzione proposta rappresenti una difesa generalmente sufficiente contro gli attacchi XSS, puoi applicare una serie di misure di hardening aggiuntive per fornire ulteriori livelli di sicurezza:

  • Imposta un'intestazione X-Content-Security-Policy: sandbox per la compatibilità con IE11.
  • Imposta un'intestazione Content-Security-Policy: frame-ancestors 'none' per impedire l'incorporamento dell'endpoint.
  • Eseguire il sandbox dei contenuti degli utenti su un sottodominio isolato:
    • Pubblicazione di contenuto dell'utente su un sottodominio isolato (ad es. 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 dell'utente attivi

La pubblicazione sicura di contenuti attivi (ad esempio immagini HTML o SVG) può essere eseguita anche senza i punti deboli dell'approccio classico al dominio sandbox.

L'opzione più semplice è sfruttare 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, i perfezionamenti in corso dei modelli di processo del browser probabilmente miglioreranno la separazione dei contenuti sandbox dalle applicazioni di incorporamento. Se gli attacchi SpectreJS e renderer compromise non rientrano nel tuo modello di minaccia, l'utilizzo del sandbox CSP è probabilmente una soluzione sufficiente. In Google abbiamo sviluppato una soluzione che può isolare completamente i contenuti attivi non attendibili modernizzando il concetto di domini sandbox. L'idea di base è:

  • Crea un nuovo dominio sandbox che viene aggiunto all'elenco dei suffissi pubblici. Ad esempio, aggiungendo exampleusercontent.com all'elenco PSL, puoi assicurarti che foo.exampleusercontent.com e bar.exampleusercontent.com siano cross-site e quindi completamente isolati l'uno dall'altro.
  • Gli URL corrispondenti a *.exampleusercontent.com/shim vengono tutti indirizzati a un file shim statico. Questo file shim contiene un breve snippet HTML e JavaScript che rimane in ascolto del gestore di eventi message ed esegue il rendering di tutti i contenuti che riceve.
  • Per utilizzarlo, il prodotto crea un iframe o una finestra di dialogo per $RANDOM_VALUE.exampleusercontent.com/shim e utilizza postMessage per inviare i contenuti non attendibili allo shim per il rendering.
  • I contenuti sottoposti a rendering vengono trasformati in un blob e visualizzati all'interno di un iframe con sandbox.

Rispetto all'approccio classico del dominio sandbox, questo garantisce che tutti i contenuti siano completamente isolati in un sito unico. Inoltre, se l'applicazione principale si occupa del recupero dei dati da visualizzare, non è più necessario utilizzare gli URL delle funzionalità.

Conclusione

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