Same-Origin-Policy

Die Same-Origin-Policy ist ein kritischer Sicherheitsmechanismus, der einschränkt, wie ein Dokument oder Skript von einem Origin auf eine Ressource aus einem anderen Origin zugreifen kann.

Sie hilft, potenziell bösartige Dokumente zu isolieren und reduziert mögliche Angriffsvektoren. Zum Beispiel verhindert sie, dass eine bösartige Website im Internet JavaScript in einem Browser ausführt, um Daten von einem Drittanbieter-Webmail-Dienst (in den der Benutzer eingeloggt ist) oder einem Firmenintranet (das durch das Fehlen einer öffentlichen IP-Adresse vor direktem Zugriff durch den Angreifer geschützt ist) zu lesen und diese Daten an den Angreifer weiterzuleiten.

Definition eines Origins

Zwei URLs haben denselben Origin, wenn das Protokoll, der Port (falls angegeben) und der Host für beide gleich sind. Dies kann als "Scheme/Host/Port-Tupel" oder einfach "Tupel" bezeichnet werden. (Ein "Tupel" ist eine Menge von Elementen, die zusammen ein Ganzes bilden - eine generische Form für Doppel-/Dreifach-/Vierfach-/Fünffach/etc.)

Die folgende Tabelle zeigt Beispiele für Origin-Vergleiche mit der URL http://store.company.com/dir/page.html:

URL Ergebnis Grund
http://store.company.com/dir2/other.html Gleiches Origin Nur der Pfad unterscheidet sich
http://store.company.com/dir/inner/another.html Gleiches Origin Nur der Pfad unterscheidet sich
https://store.company.com/page.html Fehler Unterschiedliches Protokoll
http://store.company.com:81/dir/page.html Fehler Unterschiedlicher Port (http:// ist Port 80 standardmäßig)
http://news.company.com/dir/page.html Fehler Unterschiedlicher Host

Geerbte Origins

Skripte, die von Seiten mit einer about:blank oder einer javascript: URL ausgeführt werden, erben den Origin des Dokuments, das diese URL enthält, da diese Arten von URLs keine Informationen über einen Origin-Server enthalten.

Beispielsweise wird about:blank oft als URL für neue, leere Popup-Fenster verwendet, in die das übergeordnete Skript Inhalte schreibt (z.B. über den Mechanismus Window.open()). Wenn dieses Popup ebenfalls JavaScript enthält, würde dieses Skript denselben Origin erben wie das Skript, das es erstellt hat.

data: URLs erhalten einen neuen, leeren Sicherheitskontext.

Datei-Origins

Moderne Browser behandeln den Origin von Dateien, die mit dem file:/// Schema geladen werden, normalerweise als undurchsichtige Origins. Das bedeutet, dass, wenn eine Datei andere Dateien aus demselben Ordner (z.B.) einbindet, sie nicht davon ausgehen, dass sie vom selben Origin stammen, und möglicherweise CORS-Fehler verursachen.

Beachten Sie, dass die URL-Spezifikation besagt, dass der Origin von Dateien implementationsabhängig ist, und einige Browser können Dateien im gleichen Verzeichnis oder Unterverzeichnis als gleiches Origin behandeln, obwohl dies Sicherheitsimplikationen hat.

Änderung des Origin

Warnung: Der hier beschriebene Ansatz (die Verwendung des document.domain Setters) ist veraltet, da er die durch die Same-Origin-Policy gebotenen Sicherheitsvorkehrungen untergräbt und das Origin-Modell in Browsern kompliziert, was zu Interoperabilitätsproblemen und Sicherheitsfehlern führt.

Eine Seite kann ihren eigenen Origin ändern, mit einigen Einschränkungen. Ein Skript kann den Wert von document.domain auf seine aktuelle Domain oder eine Superdomain seiner aktuellen Domain setzen. Wenn auf eine Superdomain der aktuellen Domain gesetzt, wird die kürzere Superdomain für Same-Origin-Prüfungen verwendet.

Zum Beispiel, wenn ein Skript aus dem Dokument bei http://store.company.com/dir/other.html das Folgende ausführt:

js
document.domain = "company.com";

Danach kann die Seite den Same-Origin-Check mit http://company.com/dir/page.html passieren (vorausgesetzt, dass http://company.com/dir/page.html sein document.domain auf "company.com" setzt, um anzuzeigen, dass es dies erlauben möchte - siehe document.domain für mehr). company.com könnte jedoch nicht document.domain auf othercompany.com setzen, da dies keine Superdomain von company.com ist.

Die Portnummer wird vom Browser separat geprüft. Jeder Aufruf von document.domain, einschließlich document.domain = document.domain, bewirkt, dass die Portnummer mit null überschrieben wird. Daher kann man nicht company.com:8080 dazu bringen, mit company.com zu kommunizieren, indem man nur document.domain = "company.com" im ersten setzt. Es muss in beiden gesetzt werden, damit ihre Portnummern beide null sind.

Der Mechanismus hat einige Einschränkungen. Zum Beispiel wird er ein SecurityError DOMException auslösen, wenn die document-domain Permissions-Policy aktiviert ist oder das Dokument in einem sandkastenartigen <iframe> ist, und das Ändern des Origin auf diese Weise beeinflusst nicht die Originschecks, die von vielen Web-APIs verwendet werden (z.B. localStorage, indexedDB, BroadcastChannel, SharedWorker). Eine umfassendere Liste von Fehlermöglichkeiten finden Sie in Document.domain > Failures.

Hinweis: Wenn Sie document.domain verwenden, um einem Subdomain den Zugriff auf sein übergeordnetes Domain zu ermöglichen, müssen Sie document.domain auf denselben Wert sowohl in der übergeordneten Domain als auch in der Subdomain setzen. Dies ist notwendig, selbst wenn Sie damit die übergeordnete Domain auf ihren ursprünglichen Wert zurücksetzen. Das Versäumnis, dies zu tun, kann zu Berechtigungsfehlern führen.

Netzwerkzugang zwischen verschiedenen Origins

Die Same-Origin-Policy steuert die Interaktionen zwischen zwei verschiedenen Origins, wie zum Beispiel wenn Sie fetch() oder ein <img>-Element verwenden. Diese Interaktionen werden typischerweise in drei Kategorien eingeordnet:

  • Cross-Origin-Schreibvorgänge sind normalerweise erlaubt. Beispiele sind Links, Umleitungen und Formularübermittlungen. Einige HTTP-Anfragen erfordern Preflight.
  • Cross-Origin-Einbettungen sind normalerweise erlaubt. (Beispiele sind unten aufgelistet.)
  • Cross-Origin-Lesezugriffe sind typischerweise nicht erlaubt, aber Lesezugriff wird oft durch Einbettung geleakt. Zum Beispiel können Sie die Abmessungen eines eingebetteten Bildes, die Aktionen eines eingebetteten Skripts oder die Verfügbarkeit einer eingebetteten Ressource lesen.

Hier sind einige Beispiele von Ressourcen, die Cross-Origin eingebettet werden können:

  • JavaScript mit <script src="…"></script>. Fehlermeldungen für Syntaxfehler sind nur für Skripte desselben Origins verfügbar.
  • CSS angewendet mit <link rel="stylesheet" href="…">. Aufgrund der entspannten Syntaxregeln von CSS erfordert Cross-Origin-CSS einen korrekten Content-Type-Header. Browser blockieren Stylesheet-Ladungen, wenn es eine Cross-Origin-Ladung ist, bei der der MIME-Typ falsch ist und die Ressource nicht mit einem gültigen CSS-Konstrukt beginnt.
  • Bilder, die durch <img> angezeigt werden.
  • Medien, die durch <video> und <audio> abgespielt werden.
  • Externe Ressourcen, die mit <object> und <embed> eingebettet werden.
  • Schriftarten, die mit @font-face angewendet werden. Einige Browser erlauben Cross-Origin-Schriftarten, andere erfordern dasselbe Origin.
  • Alles, was durch <iframe> eingebettet wird. Websites können den X-Frame-Options-Header verwenden, um Cross-Origin-Framing zu verhindern.

Anleitung zum Aktivieren von Cross-Origin-Zugriff

Verwenden Sie CORS, um Cross-Origin-Zugriff zu erlauben. CORS ist Teil von HTTP, das Servern ermöglicht, anzugeben, von welchen anderen Hosts ein Browser das Laden von Inhalten erlauben sollte.

Anleitung zum Blockieren von Cross-Origin-Zugriff

  • Um Cross-Origin-Schreibvorgänge zu verhindern, überprüfen Sie ein schwer zu erratendes Token in der Anfrage - bekannt als Cross-Site Request Forgery (CSRF)-Token. Sie müssen Cross-Origin-Lesungen von Seiten verhindern, die dieses Token erfordern.
  • Um Cross-Origin-Lesezugriffe auf eine Ressource zu verhindern, stellen Sie sicher, dass sie nicht eingebettet werden kann. Oft ist es notwendig, Einbettungen zu verhindern, da das Einbetten einer Ressource immer einige Informationen über sie leakt.
  • Um Cross-Origin-Einbettungen zu verhindern, stellen Sie sicher, dass Ihre Ressource nicht als eine der oben aufgelisteten einbettbaren Formate interpretiert werden kann. Browser respektieren möglicherweise nicht den Content-Type-Header. Wenn Sie beispielsweise ein <script>-Tag auf ein HTML-Dokument richten, wird der Browser versuchen, das HTML als JavaScript zu parsen. Wenn Ihre Ressource kein Einstiegspunkt zu Ihrer Website ist, können Sie auch ein CSRF-Token verwenden, um die Einbettung zu verhindern.

Zugriff auf Cross-Origin-Skript-APIs

JavaScript-APIs wie iframe.contentWindow, window.parent, window.open und window.opener erlauben es Dokumenten, sich direkt aufeinander zu beziehen. Wenn zwei Dokumente nicht denselben Origin haben, bieten diese Referenzen nur sehr begrenzten Zugriff auf Window und Location-Objekte, wie in den nächsten beiden Abschnitten beschrieben.

Um zwischen Dokumenten von verschiedenen Origins zu kommunizieren, verwenden Sie window.postMessage.

Spezifikation: HTML Living Standard § Cross-origin objects.

Window

Der folgende Cross-Origin-Zugriff auf Window-Eigenschaften ist erlaubt:

Methoden
window.blur
window.close
window.focus
window.postMessage
Attribute
window.closed Nur lesbar.
window.frames Nur lesbar.
window.length Nur lesbar.
window.location Lesen/Schreiben.
window.opener Nur lesbar.
window.parent Nur lesbar.
window.self Nur lesbar.
window.top Nur lesbar.
window.window Nur lesbar.

Einige Browser erlauben den Zugriff auf mehr Eigenschaften als die oben genannten.

Location

Der folgende Cross-Origin-Zugriff auf Location-Eigenschaften ist erlaubt:

Methoden
location.replace
Attribute
location.href Nur schreibbar.

Einige Browser erlauben den Zugriff auf mehr Eigenschaften als die oben genannten.

Zugriff auf Cross-Origin-Datenspeicherung

Der Zugriff auf im Browser gespeicherte Daten wie Web Storage und IndexedDB ist nach Origins getrennt. Jeder Origin erhält seinen eigenen separaten Speicher, und JavaScript in einem Origin kann nicht auf den Speicher eines anderen Origins zugreifen oder schreiben.

Cookies verwenden eine separate Definition von Origins. Eine Seite kann ein Cookie für ihre eigene Domain oder eine übergeordnete Domain setzen, solange die übergeordnete Domain kein öffentlicher Suffix ist. Firefox und Chrome verwenden die Public Suffix List, um zu bestimmen, ob eine Domain ein öffentlicher Suffix ist. Wenn Sie ein Cookie setzen, können Sie seine Verfügbarkeit mit den Flags Domain, Path, Secure und HttpOnly einschränken. Wenn Sie ein Cookie lesen, können Sie nicht sehen, von wo es gesetzt wurde. Selbst wenn Sie nur sichere HTTPS-Verbindungen verwenden, kann jedes Cookie, das Sie sehen, über eine unsichere Verbindung gesetzt worden sein.

Siehe auch