Hosting sicuro dei dati utente nelle moderne applicazioni web

David Dworken
David Dworken

Molte applicazioni web devono mostrare contenuti controllati dall'utente. Può essere semplice come pubblicare immagini caricate dagli utenti (ad esempio foto del profilo) o complesso come il rendering di HTML controllato dall'utente (ad esempio un tutorial di sviluppo web). È sempre stato difficile farlo in modo sicuro, quindi abbiamo cercato di trovare soluzioni semplici, ma sicure, che potessero 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, i contenuti dannosi su exampleusercontent.com non possono influire su example.com.
Questo approccio può essere utilizzato per pubblicare in sicurezza tutti i tipi di contenuti non attendibili, tra cui immagini, download e HTML. Sebbene possa sembrare non necessario utilizzarlo per le immagini o i download, questa operazione aiuta a evitare i rischi del content sniffing, in particolare nei browser precedenti.
I domini sandbox sono ampiamente utilizzati nel settore e funzionano bene da molto tempo. Tuttavia, presentano due importanti 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 dell'applicazione principale, è molto difficile eseguire questa operazione in modo sicuro. Per supportare l'autenticazione, i siti devono fare affidamento su URL delle funzionalità o impostare cookie di autenticazione separati per il dominio della sandbox. Questo secondo metodo è particolarmente problematico nel web moderno, dove molti browser limitano i cookie cross-site per impostazione predefinita.
  • Sebbene i contenuti degli utenti siano isolati dal sito principale, non lo sono dagli altri contenuti degli utenti. Ciò comporta il rischio che contenuti utente dannosi attacchino altri dati nel dominio della sandbox (ad esempio, tramite la lettura dei dati della stessa origine).

Vale anche la pena notare che i domini sandbox contribuiscono a mitigare i rischi di phishing, poiché le risorse sono segmentate in modo chiaro in un dominio isolato.

Soluzioni moderne per la pubblicazione di contenuti degli utenti

Nel tempo, il web è cambiato e ora esistono modi più semplici e sicuri per pubblicare contenuti non attendibili. Esistono molti approcci diversi, quindi illustreremo due soluzioni attualmente in uso presso Google.

Approccio 1: pubblicazione dei contenuti degli utenti non attivi

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

  • Imposta sempre l'intestazione Content-Type su un tipo MIME ben noto supportato da tutti i browser e garantito per non contenere contenuti attivi (in caso di dubbi, application/octet-stream è una scelta sicura).
  • Inoltre, imposta sempre le intestazioni di risposta riportate di seguito per assicurarti 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

Mette i contenuti in sandbox 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

Questa combinazione di intestazioni garantisce che la risposta possa essere caricata solo come risorsa secondaria dalla tua applicazione o scaricata come file dall'utente. Inoltre, le intestazioni forniscono più livelli di protezione contro i bug del browser tramite l'intestazione della sandbox CSP e la limitazione default-src. Nel complesso, la configurazione descritta sopra offre un elevato grado di certezza che le risposte fornite in questo modo non possano portare a vulnerabilità di attacco di tipo injection o di isolamento.

Difesa in profondità

Sebbene la soluzione sopra riportata rappresenti una difesa generalmente sufficiente contro gli attacchi XSS, esistono una serie di misure di rafforzamento aggiuntive che puoi applicare 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'embedding dell'endpoint.
  • Esegui la sandbox dei contenuti utente su un sottodominio isolato:
    • Pubblicazione dei contenuti 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 per utenti attivi

È anche possibile pubblicare in sicurezza contenuti attivi (ad esempio immagini HTML o SVG) senza i punti deboli dell'approccio del dominio sandbox classico.
L'opzione più semplice è utilizzare l'intestazione Content-Security-Policy: sandbox per indicare al browser di isolare la risposta. Anche se al momento non tutti i browser web implementano l'isolamento dei processi per i documenti in sandbox, i miglioramenti continui ai modelli di processo del browser potrebbero migliorare la separazione dei contenuti in sandbox dalle applicazioni di incorporamento. Se gli attacchi SpectreJS e di compromissione del rendering non rientrano nel tuo modello di minacce, l'utilizzo della 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 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 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 ascolta il gestore degli eventi message e esegue il rendering di tutti i contenuti ricevuti.
  • Per utilizzarlo, 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 del dominio sandbox, questo garantisce che tutti i contenuti siano completamente isolati in un sito unico. Inoltre, poiché 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. Google ha già eseguito la migrazione di molti prodotti a queste soluzioni e ne ha pianificate altre per il prossimo anno.