Ressourcen mit Fetch Metadata vor Webangriffen schützen

CSRF-, XSSI- und plattformübergreifende Datenlecks verhindern

Lukas Weichselbaum
Lukas Weichselbaum

Warum sollten Sie Ihre Webressourcen isolieren?

Viele Webanwendungen sind anfällig für Cross-Origin-Angriffe wie Cross-Site Request Forgery (CSRF), Cross-Site Script Inclusion (XSSI), Timing-Angriffe, Cross-Origin Information Leaks oder spekulative Ausführungs-Side-Channel-Angriffe (Spectre).

Mit den Anfrageheadern Fetch Metadata können Sie einen starken Defense-in-Depth-Mechanismus – eine Ressourcenisolierungsrichtlinie – implementieren, um Ihre Anwendung vor diesen gängigen plattformübergreifenden Angriffen zu schützen.

Häufig werden Ressourcen, die von einer bestimmten Webanwendung bereitgestellt werden, nur von der Anwendung selbst und nicht von anderen Websites geladen. In solchen Fällen ist die Implementierung einer Ressourcenisolierungsrichtlinie, die auf Anfrageheadern für das Abrufen von Metadaten basiert, mit wenig Aufwand verbunden und schützt gleichzeitig die Anwendung vor websiteübergreifenden Angriffen.

Browserkompatibilität

Anfrageheader zum Abrufen von Metadaten werden in allen modernen Browser-Engines unterstützt.

Unterstützte Browser

  • Chrome: 76
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Quelle

Hintergrund

Viele websiteübergreifende Angriffe sind möglich, weil das Internet standardmäßig offen ist und Ihr Anwendungsserver sich nicht so einfach vor der Kommunikation von externen Anwendungen schützen kann. Ein typischer ursprungsübergreifender Angriff ist Cross-Site Request Forgery (CSRF), bei dem ein Angreifer einen Nutzer auf eine von ihm kontrollierte Website lockt und dann ein Formular an den Server sendet, bei dem der Nutzer angemeldet ist. Da der Server nicht erkennen kann, ob die Anfrage von einer anderen Domain stammt (websiteübergreifend), und der Browser automatisch Cookies an websiteübergreifende Anfragen anhängt, führt der Server die vom Angreifer angeforderte Aktion im Namen des Nutzers aus.

Andere websiteübergreifende Angriffe wie Cross-Site Script Inclusion (XSSI) oder ursprungsübergreifende Informationslecks sind ähnlich wie bei CSRF. Dabei werden Ressourcen aus einer Opferanwendung in ein von Angreifern kontrolliertes Dokument geladen und Informationen über die Anwendungen des Opfers offengelegt. Da Anwendungen vertrauenswürdige Anfragen nicht einfach von nicht vertrauenswürdigen Anfragen unterscheiden können, können sie schädlichen websiteübergreifenden Traffic nicht verwerfen.

Jetzt neu: „Metadaten abrufen“

Anfrageheader zum Abrufen von Metadaten sind eine neue Sicherheitsfunktion für Webplattformen, mit der sich Server vor ursprungsübergreifenden Angriffen schützen können. Durch die Bereitstellung von Informationen zum Kontext einer HTTP-Anfrage in einer Reihe von Sec-Fetch-*-Headern können die antwortenden Server Sicherheitsrichtlinien anwenden, bevor die Anfrage verarbeitet wird. So können Entwickler entscheiden, ob sie eine Anfrage annehmen oder ablehnen möchten, je nachdem, wie sie gestellt wurde und in welchem Kontext sie verwendet wird. So ist es möglich, nur auf legitime Anfragen zu reagieren, die von ihrer eigenen Anwendung stammen.

Gleicher Ursprung
Anfragen von Websites, die von Ihrem eigenen Server (same-Origin) bereitgestellt werden, funktionieren weiterhin. Eine Abrufanfrage von https://website.de für die Ressource https://website.de/foo.json in JavaScript führt dazu, dass der Browser den HTTP-Anfrageheader „Sec Fetch-Site: same-origin“ sendet.
Websiteübergreifend
Maliziöse websiteübergreifende Anfragen können vom Server aufgrund des zusätzlichen Kontexts in der HTTP-Anfrage abgelehnt werden, der durch Sec-Fetch-*-Header bereitgestellt wird. Ein Bild auf https://evil.example, das das src-Attribut eines img-Elements auf "https://site.example/foo.json" gesetzt hat, bewirkt, dass der Browser den HTTP-Anfrageheader "Sec-Fetch-Site: Cross-site" sendet.

Sec-Fetch-Site

Unterstützte Browser

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4.

Quelle

Sec-Fetch-Site teilt dem Server mit, von welcher Website die Anfrage gesendet wurde. Der Browser legt diesen Wert auf einen der folgenden Werte fest:

  • same-origin, wenn die Anfrage von Ihrer eigenen Anwendung (z.B. site.example) gestellt wurde
  • same-site, wenn die Anfrage von einer Subdomain Ihrer Website stammt (z. B. bar.site.example)
  • none, wenn die Anfrage explizit durch die Interaktion eines Nutzers mit dem User-Agent verursacht wurde (z. B. Klicken auf ein Lesezeichen)
  • cross-site, wenn die Anfrage von einer anderen Website gesendet wurde (z. B. evil.example)

Sec-Fetch-Mode

Unterstützte Browser

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 90.
  • Safari: 16.4

Quelle

Sec-Fetch-Mode gibt den Modus der Anfrage an. Dies entspricht ungefähr dem Typ der Anfrage und ermöglicht es Ihnen, Ressourcenlasten von Navigationsanfragen zu unterscheiden. Ein Ziel von navigate gibt beispielsweise eine Navigationsanfrage auf oberster Ebene an, während no-cors für Ressourcenanfragen wie das Laden eines Bildes steht.

Sec-Fetch-Dest

Unterstützte Browser

  • Chrome: 80.
  • Edge: 80.
  • Firefox: 90.
  • Safari: 16.4

Quelle

Sec-Fetch-Dest macht das Ziel einer Anfrage verfügbar, z.B. wenn ein script- oder ein img-Tag dazu geführt hat, dass eine Ressource vom Browser angefordert wurde.

Fetch Metadata zum Schutz vor plattformübergreifenden Angriffen verwenden

Die zusätzlichen Informationen, die diese Anfrageheader liefern, sind recht einfach, aber der zusätzliche Kontext ermöglicht es Ihnen, mit nur wenigen Codezeilen eine leistungsstarke Sicherheitslogik auf der Serverseite zu erstellen, die auch als Richtlinie zur Ressourcenisolierung bezeichnet wird.

Richtlinie zur Ressourcenisolierung implementieren

Eine Richtlinie zur Ressourcenisolierung verhindert, dass Ihre Ressourcen von externen Websites angefordert werden. Durch das Blockieren solcher Zugriffe werden häufige Cross-Site-Web-Sicherheitslücken wie CSRF, XSSI, Timing-Angriffe und Cross-Origin-Informationslecks minimiert. Diese Richtlinie kann für alle Endpunkte Ihrer Anwendung aktiviert werden und erlaubt alle Ressourcenanfragen, die von Ihrer eigenen Anwendung stammen, sowie direkte Navigationen (über eine HTTP-GET-Anfrage). Für Endpunkte, die in einem websiteübergreifenden Kontext geladen werden sollen (z.B. Endpunkte, die mit CORS geladen werden), kann diese Logik deaktiviert werden.

Schritt 1: Anfragen von Browsern zulassen, die keine Abrufmetadaten senden

Da das Abrufen von Metadaten nicht von allen Browsern unterstützt wird, müssen Sie Anfragen ohne Sec-Fetch-*-Header zulassen, indem Sie prüfen, ob sec-fetch-site vorhanden ist.

if not req['sec-fetch-site']:
  return True  # Allow this request

Schritt 2: Anfragen innerhalb der Website und vom Browser initiierte Anfragen zulassen

Alle Anfragen, die nicht aus einem ursprungsübergreifenden Kontext wie evil.example stammen, werden zugelassen. Dazu gehören insbesondere Anfragen, die:

  • Sie stammen aus Ihrer eigenen Anwendung (z. B. eine Anfrage vom selben Ursprung, bei der site.example-Anfragen site.example/foo.json immer zulässig sind).
  • Sie stammen aus Ihren Subdomains.
  • Werden explizit durch die Interaktion eines Nutzers mit dem User-Agent ausgelöst, z. B. durch direkte Navigation oder durch Klicken auf ein Lesezeichen
if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
  return True  # Allow this request

Schritt 3: Einfache Navigation auf oberster Ebene und iFrames zulassen

Damit deine Website weiterhin von anderen Websites aus verlinkt werden kann, musst du eine einfache Navigation (HTTP GET) auf oberster Ebene zulassen.

if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
  # <object> and <embed> send navigation requests, which we disallow.
  and req['sec-fetch-dest'] not in ('object', 'embed'):
    return True  # Allow this request

Schritt 4: Endpunkte deaktivieren, die für websiteübergreifende Zugriffe gedacht sind (optional)

In einigen Fällen stellt Ihre Anwendung möglicherweise Ressourcen bereit, die websiteübergreifend geladen werden sollen. Diese Ressourcen müssen pro Pfad oder Endpunkt ausgenommen werden. Beispiele für solche Endpunkte:

  • Endpunkte, auf die über mehrere Ursprünge hinweg zugegriffen werden soll: Wenn Ihre Anwendung Endpunkte bereitstellt, für die CORS aktiviert ist, müssen Sie die Ressourcenisolierung für diese Endpunkte explizit deaktivieren, damit weiterhin websiteübergreifende Anfragen an diese Endpunkte möglich sind.
  • Öffentliche Ressourcen (z.B. Bilder, Stile usw.): Alle öffentlichen und nicht authentifizierten Ressourcen, die ursprungsübergreifend von anderen Websites geladen werden sollen, können ebenfalls ausgenommen werden.
if req.path in ('/my_CORS_endpoint', '/favicon.png'):
  return True

Schritt 5: Alle anderen websiteübergreifenden Anfragen ablehnen, die nicht auf Navigation zurückzuführen sind

Alle anderen websiteübergreifenden Anfragen werden von dieser Richtlinie zur Ressourcenisolierung abgelehnt und Ihre Anwendung wird so vor gängigen websiteübergreifenden Angriffen geschützt.

Beispiel:Der folgende Code zeigt eine vollständige Implementierung einer robusten Richtlinie zur Ressourcenisolierung auf dem Server oder als Middleware, mit der potenziell schädliche websiteübergreifende Ressourcenanfragen abgelehnt werden können. Gleichzeitig werden einfache Navigationsanfragen ermöglicht:

# Reject cross-origin requests to protect from CSRF, XSSI, and other bugs
def allow_request(req):
  # Allow requests from browsers which don't send Fetch Metadata
  if not req['sec-fetch-site']:
    return True

  # Allow same-site and browser-initiated requests
  if req['sec-fetch-site'] in ('same-origin', 'same-site', 'none'):
    return True

  # Allow simple top-level navigations except <object> and <embed>
  if req['sec-fetch-mode'] == 'navigate' and req.method == 'GET'
    and req['sec-fetch-dest'] not in ('object', 'embed'):
      return True

  # [OPTIONAL] Exempt paths/endpoints meant to be served cross-origin.
  if req.path in ('/my_CORS_endpoint', '/favicon.png'):
    return True

  # Reject all other requests that are cross-site and not navigational
  return False

Richtlinie zur Ressourcenisolierung bereitstellen

  1. Installieren Sie ein Modul wie das obige Code-Snippet, um das Verhalten Ihrer Website zu protokollieren und zu überwachen und sicherzustellen, dass sich die Einschränkungen nicht auf legitimen Traffic auswirken.
  2. Beheben Sie potenzielle Verstöße, indem Sie legitime ursprungsübergreifende Endpunkte ausnehmen.
  3. Sie können die Richtlinie erzwingen, indem Sie nicht konforme Anfragen löschen.

Richtlinienverstöße erkennen und beheben

Wir empfehlen, die Richtlinie ohne Nebenwirkungen zu testen. Aktivieren Sie dazu die Richtlinie zuerst im Berichterstellungsmodus in Ihrem serverseitigen Code. Alternativ können Sie diese Logik in Middleware oder in einem Reverse-Proxy implementieren, der alle Verstöße protokolliert, die bei der Anwendung Ihrer Richtlinie auf Produktionszugriffe auftreten.

Unsere Erfahrung bei der Einführung einer Richtlinie für die Isolierung von Metadatenressourcen bei Google hat ergeben, dass die meisten Anwendungen standardmäßig mit einer solchen Richtlinie kompatibel sind und nur selten ausgenommene Endpunkte erforderlich sind, um websiteübergreifenden Traffic zu ermöglichen.

Ressourcenisolationsrichtlinie erzwingen

Nachdem Sie überprüft haben, dass sich Ihre Richtlinie nicht auf legitimen Produktionstraffic auswirkt, können Sie Einschränkungen erzwingen. So wird sichergestellt, dass andere Websites Ihre Ressourcen nicht anfordern können, und Ihre Nutzer werden vor websiteübergreifenden Angriffen geschützt.

Weitere Informationen