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. Il peut s'agir d'une tâche simple, comme la diffusion d'images importées par l'utilisateur (par exemple, des photos de profil), ou d'une tâche complexe, comme l'affichage du code HTML contrôlé par l'utilisateur (par exemple, un tutoriel de développement Web). Cela a toujours été difficile à réaliser de manière sécurisée. Nous avons donc travaillé pour 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 des contenus contrôlés par l'utilisateur de manière sécurisée 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 tous les contenus non approuvés sur exampleusercontent.com. Étant donné que ces deux domaines sont intersites, tout contenu malveillant sur exampleusercontent.com ne peut pas avoir d'incidence sur example.com.
Cette approche permet de diffuser en toute sécurité tous types de contenus non approuvés, y compris des images, des téléchargements et du code HTML. Bien que cela ne semble pas nécessaire pour les images ou les téléchargements, cela permet d'éviter les risques liés au reniflage 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. Toutefois, elles 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 de cookies avec le domaine de l'application principale, cette opération est très difficile à effectuer de manière sécurisée. Pour prendre en charge l'authentification, les sites doivent soit s'appuyer sur des URL de capacité, soit définir des cookies d'authentification distincts pour le domaine du 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 ne l'est pas des autres contenus utilisateur. Cela crée le risque que du contenu utilisateur malveillant attaque d'autres données sur le domaine de bac à sable (par exemple, en lisant des données d'origine commune).

Il est également intéressant de noter que les domaines de bac à sable permettent d'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é, et 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 décrire deux solutions actuellement largement utilisées chez Google.

Méthode 1: Diffuser le contenu des utilisateurs inactifs

Si un site ne doit diffuser que du contenu utilisateur inactif (c'est-à-dire du contenu qui n'est pas HTML ni JavaScript, par exemple des images et des téléchargements), il peut désormais le faire en toute sécurité sans domaine de bac à sable isolé. Il existe deux étapes clés:

  • Définissez toujours l'en-tête Content-Type sur un type MIME bien connu, compatible avec tous les navigateurs et qui ne contient 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 ci-dessous 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 le reniflage de contenu

Content-Disposition: attachment; filename="download"

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

Content-Security-Policy: sandbox

Place le contenu dans un bac à sable comme s'il était diffusé sur un domaine distinct.

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

Désactive l'exécution JavaScript (et l'inclusion de toute sous-ressource).

Cross-Origin-Resource-Policy: same-site

Empêche l'inclusion de la page entre les sites

Cette combinaison d'en-têtes garantit que la réponse ne peut être chargée que comme sous-ressource par votre application ou téléchargée en tant que 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. De manière générale, la configuration décrite ci-dessus offre un haut niveau de confiance quant à la probabilité que les réponses diffusées de cette manière ne puissent pas entraîner de failles d'injection ou d'isolation.

Défense en profondeur

Bien que la solution ci-dessus représente une défense généralement suffisante contre les attaques XSS, vous pouvez appliquer un certain nombre de mesures de renforcement supplémentaires pour fournir des couches 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.
  • Contenu utilisateur du bac à sable sur un sous-domaine isolé :
    • Diffusion de 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 multi-origine.

Méthode 2: Diffuser du contenu pour les utilisateurs actifs

Vous pouvez également diffuser du contenu actif de manière sécurisée (par exemple, des images HTML ou SVG) sans les points faibles de l'approche classique du domaine de bac à sable.
L'option la plus simple consiste à utiliser 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 actuellement l'isolation de processus pour les documents de bac à sable, les améliorations continues des modèles de processus de navigateur devraient améliorer la séparation du contenu en bac à sable des applications d'intégration. Si les attaques SpectreJS et de compromis du moteur de rendu ne font pas partie de votre modèle de menace, l'utilisation d'un bac à sable CSP est probablement une solution suffisante.
Chez Google, nous avons développé une solution capable d'isoler complètement le contenu actif non approuvé en modernisant le concept de domaines de bac à sable. L'idée de base est la suivante:

  • Créez un domaine de bac à sable qui est ajouté à la liste de suffixes publics. Par exemple, en ajoutant exampleusercontent.com au fichier PSL, vous pouvez vous assurer que foo.exampleusercontent.com et bar.exampleusercontent.com sont intersites et donc totalement isolés l'un de l'autre.
  • Les URL correspondant à *.exampleusercontent.com/shim sont toutes acheminées vers un fichier de shim statique. Ce fichier de shim contient un court extrait 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 fenêtre pop-up pour $RANDOM_VALUE.exampleusercontent.com/shim et utilise postMessage pour envoyer le contenu non approuvé au shim pour l'affichage.
  • Le contenu affiché est converti en blob et affiché dans un iFrame en bac à sable.

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

Conclusion

Ces deux solutions permettent de migrer depuis 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 vers ces solutions, et nous prévoyons d'en migrer d'autres l'année prochaine.