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 la diffusion d'images importées par les utilisateurs (par exemple, des photos de profil) ou aussi complexe que le rendu HTML contrôlé par l'utilisateur (par exemple, un tutoriel de développement Web). Cela a toujours été difficile à faire de manière sécurisée. Nous nous sommes donc efforcés de trouver des solutions simples, mais sécurisées, qui peuvent être appliquées à la plupart des types d'applications Web.

Solutions classiques pour isoler les contenus non approuvés

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 pourrez diffuser tout le contenu non approuvé sur exampleusercontent.com. Ces deux domaines étant intersites, tout contenu malveillant sur exampleusercontent.com ne peut pas affecter example.com.
Cette approche peut être utilisée pour diffuser en toute sécurité toutes sortes de contenus non fiables, y compris des images, des téléchargements et du code HTML. Même s'il ne vous semble pas nécessaire de l'utiliser pour les images ou les téléchargements, vous pouvez éviter les risques de 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. Elles présentent toutefois deux inconvénients majeurs:

  • Les applications doivent souvent restreindre l'accès au contenu à un seul utilisateur, ce qui nécessite la mise en œuvre d'une authentification et d'une autorisation. Étant donné que les domaines de bac à sable ne partagent délibérément pas de cookies avec le domaine d'application principal, cette opération est très difficile à effectuer de manière sécurisée. Pour permettre l'authentification, les sites doivent soit se baser sur des URL de capacité, soit définir des cookies d'authentification distincts pour le domaine de bac à sable. Cette seconde méthode est particulièrement problématique sur le Web moderne, où de nombreux navigateurs limitent par défaut les cookies intersites.
  • Bien que le contenu de l'utilisateur soit isolé du site principal, il n'est pas isolé des autres. Cela crée le risque que des contenus utilisateur malveillants attaquent d'autres données dans le domaine du bac à sable (par exemple, en lisant des données de même origine).

Il convient également de noter que les domaines de bac à sable permettent de limiter les risques d'hameçonnage, car les ressources sont clairement segmentées au sein d'un domaine isolé.

Solutions modernes pour la diffusion de contenus utilisateur

Le Web a évolué au fil du temps, et il existe désormais des moyens plus simples et plus sécurisés de diffuser des contenus non fiables. Il existe de nombreuses approches différentes. Nous allons donc vous présenter deux solutions couramment utilisées par Google actuellement.

Méthode 1: diffuser le contenu des utilisateurs inactifs

Si un site doit seulement diffuser du contenu utilisateur inactif (qui n'est pas HTML ou 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é. Il y a 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 avec garantie de ne pas inclure de contenu actif (en cas de doute, application/octet-stream est un choix sûr).
  • En outre, 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 au lieu d'un affichage

Content-Security-Policy: sandbox

Met 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 toutes les 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 qu'en tant que 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 couches de protection contre les bugs des navigateurs grâce à l'en-tête de bac à sable CSP et à la restriction default-src. Dans l'ensemble, la configuration décrite ci-dessus garantit avec un haut niveau de certitude que les réponses diffusées de cette manière ne peuvent pas entraîner des 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 le XSS, vous pouvez appliquer un certain nombre de mesures de renforcement supplémentaires pour renforcer la sécurité:

  • Définissez un en-tête X-Content-Security-Policy: sandbox pour assurer 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.
  • le contenu utilisateur dans le bac à sable d'un sous-domaine isolé :
    • Diffuser le contenu d'un 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.

Approche 2: diffuser le contenu utilisateur actif

La diffusion sécurisée du contenu actif (par exemple, des images HTML ou SVG) peut également être effectuée sans les inconvénients de l'approche classique du domaine de bac à sable.
L'option la plus simple consiste à exploiter 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 actuellement pas l'isolation des processus pour les documents de bac à sable, les améliorations constantes apportées aux modèles de processus des navigateurs sont susceptibles d'améliorer la séparation entre le contenu en bac à sable et les applications d'intégration. Si les attaques SpectreJS et celles qui compromettent le moteur de rendu ne font pas partie de votre modèle de menaces, l'utilisation du bac à sable CSP est probablement une solution suffisante.
Google a développé une solution capable d'isoler entièrement le contenu actif non approuvé en modernisant le concept des domaines de bac à sable. L'idée de base est la suivante:

  • Créez un domaine de bac à sable à ajouter à la liste des suffixes publics. Par exemple, en ajoutant exampleusercontent.com à la PSL, vous pouvez vous assurer que foo.exampleusercontent.com et bar.exampleusercontent.com sont intersites et donc complètement isolés les uns des autres.
  • 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 reçu.
  • Pour utiliser cette option, le produit crée un iFrame ou un pop-up dans $RANDOM_VALUE.exampleusercontent.com/shim et utilise postMessage pour envoyer le contenu non approuvé au shim en vue de son affichage.
  • Le contenu affiché est transformé en objet blob et affiché dans un iFrame en bac à sable.

Par rapport à l'approche classique des domaines de bac à sable, cette méthode garantit que tout le contenu est entièrement isolé sur un site unique. De plus, comme l'application principale se charge de récupérer les 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 vers ces solutions et d'autres migrations sont prévues pour l'année prochaine.