Same-Origin-Policy

Die Same-Origin-Policy ist ein entscheidender Sicherheitsmechanismus, der einschränkt, wie ein Dokument oder Skript, das von einem Ursprung geladen wurde, mit einer Ressource von einem anderen Ursprung interagieren kann.

Sie hilft, potenziell schädliche Dokumente zu isolieren, indem mögliche Angriffspunkte reduziert werden. Zum Beispiel verhindert sie, dass eine bösartige Website im Internet JavaScript in einem Browser ausführt, um Daten von einem Drittanbieter-Webmail-Dienst (bei dem der Benutzer angemeldet ist) oder von einem Unternehmens-Intranet (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 Ursprungs

Zwei URLs haben denselben Ursprung, wenn das Protokoll, der Port (falls angegeben) und der Host für beide gleich sind. Dies wird oft als "Schema/Host/Port-Tupel" oder einfach "Tupel" bezeichnet. (Ein "Tupel" ist eine Menge von Elementen, die zusammen ein Ganzes bilden – eine generische Form für Doppel/Tripel/Quadruple/Quintuple/usw.)

Die folgende Tabelle gibt Beispiele für Vergleich von Ursprüngen mit der URL http://store.company.com/dir/page.html:

URL Ergebnis Grund
http://store.company.com/dir2/other.html Gleicher Ursprung Nur der Pfad unterscheidet sich
http://store.company.com/dir/inner/another.html Gleicher Ursprung Nur der Pfad unterscheidet sich
https://store.company.com/page.html Unterschied Verschiedenes Protokoll
http://store.company.com:81/dir/page.html Unterschied Verschiedener Port (http:// ist standardmäßig Port 80)
http://news.company.com/dir/page.html Unterschied Verschiedener Host

Geerbte Ursprünge

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

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

data: URLs erhalten einen neuen, leeren, Sicherheitskontext.

Datei-Ursprünge

Moderne Browser behandeln den Ursprung von Dateien, die mit dem file:/// Schema geladen werden, in der Regel als unklare Ursprünge. Das bedeutet, dass, wenn eine Datei andere Dateien aus demselben Ordner (beispielsweise) einbezieht, sie nicht als vom selben Ursprung angesehen werden und möglicherweise CORS Fehler auslösen.

Beachten Sie, dass die URL-Spezifikation besagt, dass der Ursprung von Dateien implementierungsabhängig ist, und einige Browser möglicherweise Dateien im gleichen Verzeichnis oder Unterverzeichnis als gleichartigen Ursprung behandeln, auch wenn dies Sicherheitsimplikationen hat.

Änderung des Ursprungs

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

Eine Seite kann mit einigen Einschränkungen ihren eigenen Ursprung ändern. Ein Skript kann den Wert von document.domain auf seine aktuelle Domain oder eine Superdomain seiner aktuellen Domain setzen. Wenn es auf eine Superdomain der aktuellen Domain gesetzt ist, wird die kürzere Superdomain für Überprüfungen desselben Ursprungs verwendet.

Beispielsweise, wenn ein Skript aus dem Dokument unter http://store.company.com/dir/other.html folgendes ausführt:

js
document.domain = "company.com";

Danach kann die Seite die Überprüfung desselben Ursprungs mit http://company.com/dir/page.html bestehen (vorausgesetzt, http://company.com/dir/page.html setzt sein document.domain auf "company.com", um anzuzeigen, dass es dies zulassen möchte - siehe document.domain für mehr). Allerdings könnte company.com nicht document.domain auf othercompany.com setzen, da das keine Superdomain von company.com ist.

Die Portnummer wird separat vom Browser überprü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 mit company.com allein durch das Setzen von document.domain = "company.com" im ersten kommunizieren lassen. Es muss in beiden gesetzt werden, damit ihre Portnummern beide null sind.

Der Mechanismus hat einige Einschränkungen. Zum Beispiel wird er einen SecurityError DOMException werfen, wenn das document-domain Permissions-Policy aktiviert ist oder das Dokument in einem sandboxed <iframe> ist, und die Änderung des Ursprungs auf diese Weise beeinflusst nicht die Ursprungsüberprüfungen, die von vielen Web-APIs verwendet werden (z. B. localStorage, indexedDB, BroadcastChannel, SharedWorker). Eine umfangreichere Liste von Fehlschlägen finden Sie in Document.domain > Failures.

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

Netzwerkzugriff über Ursprungsgrenzen hinweg

Die Same-Origin-Policy steuert Interaktionen zwischen zwei verschiedenen Ursprüngen, wie z.B. wenn Sie fetch() oder ein <img> Element verwenden. Diese Interaktionen werden typischerweise in drei Kategorien eingeteilt:

  • Schreibzugriffe über Ursprungsgrenzen hinweg sind typischerweise erlaubt. Beispiele sind Links, Weiterleitungen und Formularübermittlungen. Einige HTTP-Anfragen erfordern Preflight.
  • Einbettungen über Ursprungsgrenzen hinweg sind typischerweise erlaubt. (Beispiele sind unten aufgeführt.)
  • Lesezugriffe über Ursprungsgrenzen hinweg sind typischerweise nicht erlaubt, aber Lesezugriffe werden häufig durch Einbettung geleakt. Beispielsweise 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 für Ressourcen, die über Ursprungsgrenzen hinweg eingebettet werden können:

  • JavaScript mit <script src="…"></script>. Fehlermeldungen für Syntaxfehler sind nur für Skripte desselben Ursprungs verfügbar.
  • CSS angewendet mit <link rel="stylesheet" href="…">. Aufgrund der entspannten Syntaxregeln von CSS erfordert CSS über Ursprungsgrenzen hinweg einen korrekten Content-Type Header. Browser blockieren das Laden von Stylesheets, wenn es sich um ein Laden über Ursprungsgrenzen hinweg handelt, wo der MIME-Typ falsch ist und die Ressource nicht mit einem gültigen CSS-Konstrukt beginnt.
  • Bilder angezeigt durch <img>.
  • Medien abgespielt durch <video> und <audio>.
  • Externe Ressourcen eingebettet mit <object> und <embed>.
  • Schriftarten angewendet mit @font-face. Einige Browser erlauben Schriftarten über Ursprungsgrenzen, andere erfordern den gleichen Ursprung.
  • Alles eingebettet durch <iframe>. Websites können den X-Frame-Options Header verwenden, um das Einrahmen über Ursprungsgrenzen zu verhindern.

Anleitung zur Erlaubnis von Zugriff über Ursprungsgrenzen hinweg

Verwenden Sie CORS, um den Zugriff über Ursprungsgrenzen hinweg zu erlauben. CORS ist ein Teil von HTTP, der es Servern ermöglicht, spezifische andere Hosts anzugeben, von denen ein Browser das Laden von Inhalten erlauben soll.

Anleitung zur Blockierung des Zugriffs über Ursprungsgrenzen hinweg

  • Um Schreibzugriffe über Ursprungsgrenzen hinweg zu verhindern, prüfen Sie ein nicht erratbares Token in der Anfrage – bekannt als Cross-Site Request Forgery (CSRF) Token. Sie müssen Lesezugriffe auf Seiten verhindern, die dieses Token erfordern.
  • Um Lesezugriffe über Ursprungsgrenzen auf eine Ressource zu verhindern, stellen Sie sicher, dass sie nicht eingebettet werden kann. Es ist oft notwendig, das Einbetten zu verhindern, da das Einbetten einer Ressource immer einige Informationen darüber leakt.
  • Um Einbettungen über Ursprungsgrenzen hinweg zu verhindern, stellen Sie sicher, dass Ihre Ressource nicht als eines der oben aufgeführten einbettbaren Formate interpretiert werden kann. Browser respektieren möglicherweise nicht den Content-Type Header. Beispielsweise, wenn Sie ein <script> Tag auf ein HTML-Dokument verweisen, wird der Browser versuchen, das HTML als JavaScript zu interpretieren. Wenn Ihre Ressource kein Einstiegspunkt Ihrer Website ist, können Sie auch ein CSRF-Token verwenden, um das Einbetten zu verhindern.

Skript-API-Zugriff über Ursprungsgrenzen

JavaScript-APIs wie iframe.contentWindow, window.parent, window.open, und window.opener ermöglichen es Dokumenten, direkt aufeinander zu verweisen. Wenn zwei Dokumente nicht denselben Ursprung haben, bieten diese Verweise nur sehr eingeschränkten Zugriff auf Window und Location Objekte, wie in den nächsten beiden Abschnitten beschrieben.

Um zwischen Dokumenten von verschiedenen Ursprüngen zu kommunizieren, verwenden Sie window.postMessage.

Spezifikation: HTML Living Standard § Cross-origin objects.

Window

Der folgende Zugriff über Ursprungsgrenzen auf diese Window Eigenschaften ist erlaubt:

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

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

Location

Der folgende Zugriff über Ursprungsgrenzen auf Location Eigenschaften ist erlaubt:

Methoden
location.replace
Attribute
location.href Nur Schreiben.

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

Zugriff auf Datenspeicherung über Ursprungsgrenzen

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

Cookies verwenden eine separate Definition von Ursprüngen. Eine Seite kann ein Cookie für ihre eigene Domain oder jede ü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. Beim Setzen eines Cookies können Sie dessen Verfügbarkeit mit den Flags Domain, Path, Secure und HttpOnly einschränken. Beim Lesen eines Cookies können Sie nicht sehen, woher es gesetzt wurde. Auch wenn Sie nur sichere HTTPS-Verbindungen verwenden, kann jedes Cookie, das Sie sehen, mit einer unsicheren Verbindung gesetzt worden sein.

Siehe auch