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:
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 korrektenContent-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 denX-Frame-Options
Header verwenden, um das Einrahmen über Ursprungsgrenzen zu verhindern.
Anleitung zur Erlaubnis von Zugriff über Ursprungsgrenzen hinweg
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:
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.