Geschrieben von

COOP, COEP und CORP

WebDev

In diesem Beitrag geht es um die HTTP-Header COOP, COEP und CORP. Doch zunächst einmal etwas zum Hintergrund.

Hintergrund: Same-Origin-Policy

Sicherheit im Web spielt eine sehr wichtige Rolle. Wenn der Nutzer eine Website aufruft, dann schickt der Browser zunächst eine Anfrage an den Server, der die HTML-Datei ausliefert. Über das HTML sind wiederum Ressourcen verlinkt, die wieder eine Anfrage zum Server auslösen. Ein klassisches Beispiel sind Bilder. Diese werden entweder vom gleichen Server wie die HTML-Datei oder von einem anderen Server wie bspw. einem CDN angefragt. Zudem sind im HTML verschiedene JavaScript-Dateien eingebunden, die zusätzliche Anfragen zu fremden Servern initiieren, damit bestimmte Ressourcen bereitgestellt werden. Klassische Beispiele sind auch hier Bilder, aber auch externe Consent Layer und Anzeigen.

Bei den Anfragen kann man dann grundsätzlich unterscheiden in:

  • Same-Origin: Anfragen, die immer zur selben Domain gehen. Fordert der Nutzer z.B. die Website www.beispiel.de an und werden dabei Bilder von www.beispiel.de geladen, dann sprechen wir von der gleichen Herkunft (also Same-Origin).
  • Cross-Origin: Anfragen, die domainübergreifend sind. Fordert der Nutzer z.B. die Website www.beispiel.de an und werden dabei Ressourcen von www.fremdeseite.de geladen, dann sprechen wir von einer Cross-Origin-Anfrage.

Um zu bestimmen, was Same-Origin und was Cross-Origin ist, kommt es zu einem Vergleich der Herkunft der Anfrage. Für den Vergleich werden 3 Komponenten einer URL herangezogen:

  • Protokoll
  • Domain
  • Port

Die Regeln dahinter sind dann ganz einfach: Nur wenn alle drei Komponenten bei Herkunfts- und Anfrage-URL übereinstimmen, ist die Same-Origin-Policy gegeben und ein Zugriff wird erlaubt. Um das zu verdeutlichen, nehmen wir als Beispiel die URL https://www.beispiel.de/verzeichnis/seite1.html. Auf dieser Seite versucht nun ein Skript auf Ressourcen der nachfolgenden Seiten zuzugreifen. Folgende Anfragen werden erlaubt, da Protokoll, Domain und Port mit der Herkunfts-URL übereinstimmen:

  • https://www.beispiel.de/verzeichnis/seite2.html
  • https://www.beispiel.de/verzeichnis/unterverzeichnis/seite2.html

Folgende Anfragen würden jedoch von der Same-Origin-Policy abgelehnt werden:

  • http://www.beispiel.de/verzeichnis/seite1.html (anderes Protokoll)
  • https://www.beispiel.de:81/verzeichnis/seite1.html (anderer Port)
  • https://abc.beispiel.de/verzeichnis/seite1.html (anderer Host)

Seit der Einführung der Same-Site-Policy ist sie ein wichtiges Sicherheitskonzept, jedoch gibt es Fälle, wo man explizit Ressourcen anderer Herkunft auf der eigenen Website laden möchte. Hier kam dann CORS (Cross-Origin Resource Sharing) ins Spiel. Bevor wir zu CORS kommen, muss auch gesagt werden, dass die Same-Site-Policy mit der Zeit diverse “Lockerungen” eingeführt hat. Generell und grob lässt sich festhalten, dass Cross-Origin-Ressourcen eingebettet werden können, jedoch ist das Lesen dieser Ressourcen gesperrt. Diese Lockerungen und Restriktionen sind aber auch von der Ressourcen-Art abhängig. Nachfolgend eine kleine Übersicht, bevor es mit CORS weitergeht.

  • Skripte: Cross-Origin-Skripte lassen sich grundsätzlich einbetten. Jedoch kann es sein, dass der Zugriff auf bestimmte Funktionen und APIs gesperrt ist.
  • iFrames: Einbettung von Cross-Origin-iFrames ist standardmäßig erlaubt. Ausnahmen können jedoch über den X-Frame-Options-Header definiert werden. Lesen von Inhalten und DOM-Elementen per JavaScript in iFrames, die von Cross-Origin-Anfragen stammen, ist dann nicht erlaubt.
  • Bilder: Einbetten erlaubt, Lesen von bestimmten Daten (z.B. per JavaScript) jedoch nicht.
  • CSS: Cross-Origin-CSS kann per link-Element oder per @import-CSS-Funktion einbettet werden.
  • Formulare: Im Action-Attribut kann eine fremde URL angegeben werden.
  • Video und Audio: Können per video- und audio-Tags eingebettet werden.

CORS

Wie oben geschrieben kann man mit CORS Einschränkungen der Same-Origin-Policy umgehen, um auf Ressourcen eines Servers anderen Ursprungs (Origin) zuzugreifen. Da jedoch mit der Zeit die Same-Site-Policy Lockerungen erhielt, wurde CORS auch primär als Schutz auf dem Drittanbieter-Server genutzt, um die gemeinsame Nutzung einer angefragten Ressource explizit zuzulassen. Dafür werden zusätzliche HTTP-Header verwendet. Über diese Header teilt man dem Browser mit, dass eine Berechtigung für die angefragte Ressource besteht. Gehen wir davon aus, dass wir eine Website https://www.domain1.com haben. Auf dieser Website sind 2 Bilder eingebunden:

Ein Bild wird über XMLHttpRequest oder der fetch()-Methode von der gleichen Domain angefordert. Der Server liefert das Bild ganz normal aus:

Nun wird das zweite Bilder über XMLHttpRequest oder fetch angefordert. Das Bild liegt aber auf einem anderen Server bzw. auf einer anderen Domain namens https://www.domain2.com:

Die Auslieferung wird jedoch abgelehnt, da die entsprechenden Header fehlen. Damit die Anfrage erfolgreich ausgeführt werden kann, muss www.domain2.com im Response folgenden Header mitgeben (auch bekannt als “ACAO-Header”):

Access-Control-Allow-Origin: https://www.domain1.com

Damit “gewährt” domain2.com den Zugriff auf die Ressource für domain1.com. Falls es sich jedoch um eine Ressource handelt, die von vielen Websites angefordert wird, könnte domain2.com auch folgenden Header setzen:

Access-Control-Allow-Origin: *

Der Stern ist dabei eine Wildcard und erlaubt den Zugriff allen Domains. In bestimmten Fällen macht diese Einstellung Sinn, jedoch für sensible und vertrauliche Informationen sollte diese Einstellung vermieden werden.

COOP, COEP und CORP

Trotz der Sicherheitseinstellungen, die CORS und die Same-Origin-Policy mitbringen, gab es einige Probleme. Bekannt sind z.B. XSLeaks und Spectre. Beim letzteren wurden Angriffe insbesondere durch den Einsatz diverser APIs ermöglicht, wie SharedArrayBuffer, performance.measureUserAgentSpecificMemory(), performance.now() und performance.timeOrigin.

Um diese Sicherheitslücken zu schließen wurden einige APIs zwischenzeitlich abgeschaltet. Für die Nutzung der genannten APIs muss aktuell eine Art “Opt-In” über gesonderte HTTP-Header erfolgen. Der erste Header wäre COEP.

Cross Origin Embedder Policy (COEP)

COEP verhindert das Laden von Cross-Origin-Ressourcen, außer es wurde über CORP oder CORS explizit eine Erlaubnis gesetzt. Der Header wird wie folgt genutzt:

Cross-Origin-Embedder-Policy: require-corp

Damit können Ressourcen nur über die eigene Origin laden. Ausnahmen werden über CORS oder CORP gesetzt.

Cross Origin Resource Sharing (CORS)

Zu CORS habe ich weiter oben schon geschrieben. Falls die fremde Domain einen CORS-Header setzt, um die Anfrage zu erlauben, muss auf Anfrage-Seite sichergestellt werden, dass die Anfrage nicht sofort von COEP geblockt wird. Aus diesem Grund sollte das crossorigin-Attribut verwendet werden, damit der Request in den CORS-Modus wechselt und im ersten Schritt zunächst eine Anfrage stellen kann. Erst wenn die Anfrage mit den richtigen CORS-Headern beantwortet wird, kann die Ressource geladen werden.

Am Beispiel eines Bildes erfolgt die Implementierung wie folgt:

<img scr="https://www.fremdeseite.de/bild.png" crossorigin>

Mehr zum crossorigin-Attribut gibt es auf der Mozilla-Seite.

Cross Origin Resource Policy (CORP)

CORP wird eingesetzt, um die eigenen Ressourcen davor zu schützen, von anderen Origins geladen zu werden. CORP ist sozusagen die Gegenseite von COEP. Der Header lautet dabei “Cross-Origin-Resource-Policy” und kann verschiedene Werte annehmen:

Cross-Origin-Resource-Policy: same-site
Cross-Origin-Resource-Policy: same-origin
Cross-Origin-Resource-Policy: cross-origin

Die Werte sollten selbsterklärend sein.

Cross Origin Opener Policy (COOP)

Mit COOP lässt sich weiters definieren, ob die Herkunfts-Seite für Fenster (Popups) aus anderen Origins die window.opener-Eigenschaften freigibt oder nicht. COOP isoliert das Dokument und Popups können somit nicht mehr auf das globale Objekt zugreifen. Mögliche Werte sind:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin-allow-popups
Cross-Origin-Opener-Policy: unsafe-none

Zusammenfassung

Auf Basis dieser Informationen lässt sich sagen, dass der Zugriff auf SharedArrayBuffer oder performance.measureUserAgentSpecificMemory() nur möglich ist, wenn…

  • …COEP den Wert “require-corp” besitzt…
  • …und COOP auf “same-origin” gesetzt wird.

Das Ergebnis: Die Eigenschaft window.crossOriginIsolated wird auf true gesetzt und es kann dann auf die genannten Methoden zugegriffen werden. COEP + COOP ergeben also die “Cross-Origin-Isolierung”.