Hébergement sécurisé des données utilisateur dans les applications Web modernes

David Dworken
David Dworken

De nombreuses applications Web doivent afficher du contenu contrôlé par l'utilisateur. Cela peut être aussi simple que de diffuser des images importées par l'utilisateur (par exemple, des photos de profil) ou aussi complexe que de restituer du code HTML contrôlé par l'utilisateur (par exemple, un tutoriel de développement Web). Il a toujours été difficile de le faire de manière sécurisée. Nous avons donc travaillé à trouver des solutions simples, mais sécurisées, qui peuvent être appliquées à la plupart des types d'applications Web.

Solutions classiques pour isoler le contenu non approuvé

La solution classique pour diffuser de manière sécurisée du contenu contrôlé par l'utilisateur consiste à utiliser ce que l'on appelle des domaines de bac à sable. L'idée de base est que si le domaine principal de votre application est example.com, vous pouvez diffuser tout le contenu non approuvé sur exampleusercontent.com. Étant donné que ces deux domaines sont intersites, tout contenu malveillant sur exampleusercontent.com ne peut pas avoir d'impact sur example.com. Cette approche peut être utilisée pour diffuser en toute sécurité tous les types de contenu non approuvé, y compris les images, les téléchargements et le code HTML. Bien qu'il ne semble pas nécessaire de l'utiliser pour les images ou les téléchargements, cela permet d'éviter les risques liés à la détection de contenu, en particulier dans les anciens navigateurs. Les domaines de bac à sable sont largement utilisés dans le secteur et fonctionnent bien depuis longtemps. Cependant, ils présentent deux inconvénients majeurs :

  • Les applications doivent souvent limiter l'accès au contenu à un seul utilisateur, ce qui nécessite d'implémenter l'authentification et l'autorisation. Étant donné que les domaines de bac à sable ne partagent pas intentionnellement les cookies avec le domaine principal de l'application, il est très difficile de le faire de manière sécurisée. Pour prendre en charge l'authentification, les sites doivent s'appuyer sur des URL de capacité ou définir des cookies d'authentification distincts pour le domaine de bac à sable. Cette deuxième méthode est particulièrement problématique sur le Web moderne, où de nombreux navigateurs limitent les cookies intersites par défaut.
  • Bien que le contenu utilisateur soit isolé du site principal, il n'est pas isolé des autres contenus utilisateur. Cela crée un risque de contenu utilisateur malveillant attaquant d'autres données sur le domaine de bac à sable (par exemple, en lisant des données de même origine).

Il convient également de noter que les domaines de bac à sable contribuent à atténuer les risques de hameçonnage, car les ressources sont clairement segmentées sur un domaine isolé.

Solutions modernes pour diffuser du contenu utilisateur

Au fil du temps, le Web a évolué. Il existe désormais des moyens plus simples et plus sécurisés de diffuser du contenu non approuvé. Il existe de nombreuses approches différentes. Nous allons donc présenter deux solutions que nous utilisons chez Google.

Méthode 1 : Diffuser du contenu utilisateur inactif

Si un site n'a besoin de diffuser que du contenu utilisateur inactif (c'est-à-dire du contenu qui n'est pas du code HTML ni du code JavaScript, par exemple des images et des téléchargements), cela peut désormais être fait en toute sécurité sans domaine de bac à sable isolé. Vous devez procéder en deux étapes clés :

  • Définissez toujours l'en-tête Content-Type sur un type MIME connu, compatible avec tous les navigateurs et ne contenant pas de contenu actif. En cas de doute, application/octet-stream est un choix sûr.
  • De plus, définissez toujours les en-têtes de réponse pour vous assurer que le navigateur isole complètement la réponse.
En-tête de réponse Purpose

X-Content-Type-Options: nosniff

Empêche la détection de contenu

Content-Disposition: attachment; filename="download"

Déclenche un téléchargement plutôt qu'un rendu

Content-Security-Policy: sandbox

Met le contenu en bac à sable comme s'il était diffusé sur un domaine distinct

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

Désactive l'exécution de JavaScript (et l'inclusion de sous-ressources)

Cross-Origin-Resource-Policy: same-site

Empêche l'inclusion de la page sur plusieurs sites

Cette combinaison d'en-têtes garantit que la réponse ne peut être chargée que sous forme de sous-ressource par votre application ou téléchargée sous forme de fichier par l'utilisateur. De plus, les en-têtes offrent plusieurs niveaux de protection contre les bugs du navigateur via l'en-tête de bac à sable CSP et la restriction default-src. Dans l'ensemble, la configuration décrite offre un degré de confiance élevé que les réponses diffusées de cette manière ne peuvent pas entraîner de vulnérabilités d'injection ou d'isolation.

Défense en profondeur

Bien que la solution proposée représente une défense généralement suffisante contre les XSS, vous pouvez appliquer un certain nombre de mesures de renforcement supplémentaires pour fournir des niveaux de sécurité supplémentaires :

  • Définissez un en-tête X-Content-Security-Policy: sandbox pour la compatibilité avec IE11.
  • Définissez un en-tête Content-Security-Policy: frame-ancestors 'none' pour empêcher l'intégration du point de terminaison.
  • Mettez en bac à sable le contenu utilisateur sur un sous-domaine isolé :
    • Diffusez le contenu utilisateur sur un sous-domaine isolé (par exemple, Google utilise des domaines tels que product.usercontent.google.com).
    • Définissez Cross-Origin-Opener-Policy: same-origin et Cross-Origin-Embedder-Policy: require-corp pour activer l'isolation inter-origine.

Méthode 2 : Diffuser du contenu utilisateur actif

La diffusion sécurisée de contenu actif (par exemple, des images HTML ou SVG) peut également être effectuée sans les faiblesses de l'approche classique du domaine de bac à sable.

L'option la plus simple consiste à tirer parti de l'en-tête Content-Security-Policy: sandbox pour indiquer au navigateur d'isoler la réponse. Bien que tous les navigateurs Web n'implémentent pas l'isolation des processus pour les documents de bac à sable, les améliorations continues apportées aux modèles de processus de navigateur devraient améliorer la séparation du contenu mis en bac à sable des applications d'intégration. Si les attaques SpectreJS et de compromission du moteur de rendu ne font pas partie de votre modèle de menace, l'utilisation du bac à sable CSP est probablement une solution suffisante. Chez Google, nous avons développé une solution qui peut isoler complètement le contenu actif non approuvé en modernisant le concept de domaines de bac à sable. L'idée principale est la suivante :

  • Créez un domaine de bac à sable qui est ajouté à la liste des suffixes publics. Par exemple, en ajoutant exampleusercontent.com à la liste des suffixes publics, vous pouvez vous assurer que foo.exampleusercontent.com et bar.exampleusercontent.com sont intersites et donc complètement isolés l'un de l'autre.
  • Les URL correspondant à *.exampleusercontent.com/shim sont toutes acheminées vers un fichier shim statique. Ce fichier shim contient un court extrait de code HTML et JavaScript qui écoute le gestionnaire d'événements message et affiche tout contenu qu'il reçoit.
  • Pour ce faire, le produit crée un iFrame ou une boîte de dialogue pour $RANDOM_VALUE.exampleusercontent.com/shim et utilise postMessage pour envoyer le contenu non approuvé au shim pour le rendu.
  • Le contenu rendu est transformé en blob et affiché dans un iFrame en bac à sable.

Par rapport à l'approche classique du domaine de bac à sable, cela garantit que tout le contenu est complètement isolé sur un site unique. De plus, comme l'application principale gère la récupération des données à afficher, il n'est plus nécessaire d'utiliser des URL de capacité.

Conclusion

Ensemble, ces deux solutions permettent de migrer des domaines de bac à sable classiques tels que googleusercontent.com vers des solutions plus sécurisées compatibles avec le blocage des cookies tiers. Chez Google, nous avons déjà migré de nombreux produits pour utiliser ces solutions et prévoyons d'autres migrations pour l'année prochaine.