Sicheres Hosting von Nutzerdaten in modernen Webanwendungen

David Dworken
David Dworken

Viele Webanwendungen müssen nutzergesteuerten Inhalt anzeigen. Dies kann einfach das Bereitstellen von von Nutzern hochgeladenen Bildern (z. B. Profilfotos) oder so komplex wie das Rendern von nutzergesteuertem HTML (z. B. eine Anleitung zur Webentwicklung) sein. Es war immer schwierig, eine sichere Lösung zu finden. Daher suchen wir nach einfachen, aber sicheren Lösungen, die sich auf die meisten Arten von Webanwendungen anwenden lassen.

Klassische Lösungen zum Isolieren nicht vertrauenswürdiger Inhalte

Die klassische Lösung für die sichere Bereitstellung von Inhalten, die von Nutzern gesteuert werden, sind sogenannte Sandbox-Domains. Lautet die Hauptdomain Ihrer Anwendung example.com, können alle nicht vertrauenswürdigen Inhalte auf exampleusercontent.com bereitgestellt werden. Da diese beiden Domains websiteübergreifend sind, haben schädliche Inhalte auf exampleusercontent.com keine Auswirkungen auf example.com.
Mit diesem Ansatz lassen sich alle Arten von nicht vertrauenswürdigen Inhalten sicher bereitstellen, darunter Bilder, Downloads und HTML. Auch wenn es nicht unbedingt notwendig zu sein scheint, diese Funktion für Bilder oder Downloads zu verwenden, wird dadurch das Risiko des Sniffing von Inhalten vermieden, insbesondere in älteren Browsern.
Sandbox-Domains sind in der Branche weit verbreitet und funktionieren schon seit Langem gut. Es gibt jedoch zwei wesentliche Nachteile:

  • Anwendungen müssen häufig den Zugriff auf Inhalte auf einen einzelnen Nutzer beschränken, was die Implementierung von Authentifizierung und Autorisierung erfordert. Da Sandbox-Domains absichtlich Cookies nicht mit der Hauptdomain der Anwendung teilen, ist dies sehr schwierig sicher. Für die Authentifizierung müssen Websites entweder Funktions-URLs verwenden oder separate Authentifizierungs-Cookies für die Sandbox-Domain setzen. Diese zweite Methode ist besonders problematisch im modernen Web, da viele Browser websiteübergreifende Cookies standardmäßig einschränken.
  • Nutzerinhalte werden zwar von der Hauptwebsite, aber nicht von anderen Nutzerinhalten isoliert. Dadurch besteht die Gefahr, dass böswillige Nutzerinhalte andere Daten in der Sandbox-Domain angreifen (z. B. durch Lesen von Same-Origin-Daten).

Sandbox-Domains helfen dabei, das Phishing-Risiko zu verringern, da die Ressourcen eindeutig auf eine isolierte Domain aufgeteilt sind.

Moderne Lösungen zum Bereitstellen von Nutzerinhalten

Im Laufe der Zeit hat sich das Web weiterentwickelt und es gibt heute einfachere und sicherere Möglichkeiten, nicht vertrauenswürdige Inhalte bereitzustellen. Dafür gibt es viele verschiedene Ansätze. Deshalb möchten wir zwei Lösungen vorstellen, die bei Google derzeit weit verbreitet sind.

Methode 1: Inaktive Nutzerinhalte bereitstellen

Wenn auf einer Website nur inaktive Nutzerinhalte bereitgestellt werden müssen (d. h. Inhalte ohne HTML oder JavaScript, z. B. Bilder und Downloads), ist dies jetzt ohne isolierte Sandbox-Domain möglich. Es gibt zwei wichtige Schritte:

  • Setzen Sie den Content-Type-Header immer auf einen bekannten MIME-Typ, der von allen Browsern unterstützt wird und garantiert keine aktiven Inhalte enthält. Im Zweifelsfall ist application/octet-stream eine sichere Wahl.
  • Legen Sie außerdem immer die folgenden Antwortheader fest, um sicherzustellen, dass der Browser die Antwort vollständig isoliert.
Antwortheader Purpose

X-Content-Type-Options: nosniff

Verhindert das Sniffing

Content-Disposition: attachment; filename="download"

Löst einen Download aus, anstatt ihn zu rendern

Content-Security-Policy: sandbox

Der Inhalt wird in einer Sandbox ausgeführt, als würde er auf einer separaten Domain bereitgestellt werden.

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

Deaktiviert die JavaScript-Ausführung (und die Einbeziehung von Unterressourcen)

Cross-Origin-Resource-Policy: same-site

Verhindert, dass die Seite websiteübergreifend aufgenommen wird

Durch diese Kombination von Headern wird sichergestellt, dass die Antwort von Ihrer Anwendung nur als Unterressource geladen oder vom Nutzer als Datei heruntergeladen werden kann. Darüber hinaus bieten die Header über den CSP-Sandbox-Header und die default-src-Einschränkung einen mehrschichtigen Schutz vor Browserfehlern. Insgesamt bietet die oben beschriebene Konfiguration ein hohes Maß an Sicherheit, dass auf diese Weise bereitgestellte Antworten nicht zu Sicherheitslücken bei der Injektion oder Isolierung führen können.

Gestaffelte Sicherheitsebenen

Während die obige Lösung im Allgemeinen einen ausreichenden Schutz vor XSS bietet, gibt es eine Reihe zusätzlicher Härtungsmaßnahmen, die Sie anwenden können, um zusätzliche Sicherheitsebenen bereitzustellen:

  • Lege einen X-Content-Security-Policy: sandbox-Header für die Kompatibilität mit Internet Explorer 11 fest.
  • Legen Sie einen Content-Security-Policy: frame-ancestors 'none'-Header fest, um zu verhindern, dass der Endpunkt eingebettet wird.
  • Sandbox für Nutzerinhalte in einer isolierten Subdomain durch:
    • Bereitstellung von Nutzerinhalten auf einer isolierten Subdomain (z.B. Google verwendet Domains wie product.usercontent.google.com).
    • Legen Sie Cross-Origin-Opener-Policy: same-origin und Cross-Origin-Embedder-Policy: require-corp fest, um die ursprungsübergreifende Isolierung zu aktivieren.

Methode 2: Aktive Nutzerinhalte bereitstellen

Das sichere Bereitstellen aktiver Inhalte (z. B. HTML- oder SVG-Bilder) kann auch ohne die Schwächen der klassischen Sandbox-Domain erfolgen.
Die einfachste Möglichkeit besteht darin, den Content-Security-Policy: sandbox-Header zu nutzen, um den Browser anzuweisen, die Antwort zu isolieren. Derzeit implementieren nicht alle Webbrowser die Prozessisolation für Sandbox-Dokumente. Durch fortlaufende Optimierungen an den Browser-Prozessmodellen wird jedoch wahrscheinlich die Trennung von Inhalten, die in der Sandbox ausgeführt werden, von eingebetteten Anwendungen verbessert. Wenn SpectreJS- und Renderer-Manipulationsangriffe außerhalb Ihres Bedrohungsmodells liegen, ist die Verwendung der CSP-Sandbox wahrscheinlich eine ausreichende Lösung.
Google hat eine Lösung entwickelt, mit der sich nicht vertrauenswürdige aktive Inhalte vollständig isolieren lassen. Dazu wurde das Konzept von Sandbox-Domains modernisiert. Die Kernidee ist folgende:

  • Erstellen Sie eine neue Sandbox-Domain, die der öffentlichen Suffixliste hinzugefügt wird. Wenn du zum Beispiel exampleusercontent.com zur PSL hinzufügst, kannst du dafür sorgen, dass foo.exampleusercontent.com und bar.exampleusercontent.com websiteübergreifend und somit vollständig voneinander isoliert sind.
  • URLs, die mit *.exampleusercontent.com/shim übereinstimmen, werden alle an eine statische Shim-Datei weitergeleitet. Diese Shim-Datei enthält ein kurzes HTML- und JavaScript-Snippet, das den message-Event-Handler überwacht und alle empfangenen Inhalte rendert.
  • Dazu erstellt das Produkt entweder einen iFrame oder ein Pop-up für $RANDOM_VALUE.exampleusercontent.com/shim und verwendet postMessage, um die nicht vertrauenswürdigen Inhalte zum Rendern an den Shim zu senden.
  • Der gerenderte Inhalt wird in einen Blob umgewandelt und in einem in einer Sandbox ausgeführten iFrame gerendert.

Verglichen mit dem klassischen Sandbox-Domainansatz wird dadurch sichergestellt, dass alle Inhalte auf einer einzelnen Website vollständig isoliert sind. Da die Hauptanwendung die gerenderten Daten abruft, ist es außerdem nicht mehr erforderlich, Funktions-URLs zu verwenden.

Fazit

Mit diesen beiden Lösungen können Sie von klassischen Sandbox-Domains wie googleusercontent.com zu sichereren Lösungen migrieren, die mit der Blockierung von Drittanbieter-Cookies kompatibel sind. Wir haben bereits viele Produkte für diese Lösungen migriert und haben für das nächste Jahr weitere Migrationen geplant.