Same-Origin-Policy
Die Same-Origin-Policy ist ein kritischer Sicherheitsmechanismus, der einschränkt, wie ein von einem Origin geladenes Dokument oder Skript mit einer Ressource eines anderen Origin interagieren kann.
Er hilft, potenziell bösartige Dokumente zu isolieren und mögliche Angriffspunkte zu reduzieren. Zum Beispiel verhindert er, dass eine bösartige Website im Internet JS in einem Browser ausführt, um Daten von einem Drittanbieter-Webmail-Service (bei dem der Benutzer angemeldet ist) oder einem Unternehmensintranet (das vor direktem Zugriff durch den Angreifer geschützt ist, da es keine öffentliche IP-Adresse hat) zu lesen und diese Daten an den Angreifer weiterzuleiten.
Definition eines Origin
Zwei URLs haben denselben Origin, wenn das Protokoll, der Port (falls angegeben) und der Host für beide gleich sind. Dies wird oft als "Scheme/Host/Port-Tupel" oder einfach "Tupel" bezeichnet. (Ein "Tupel" ist eine Gruppe von Elementen, die zusammen eine Einheit bilden – eine allgemeine Form für Doppel/Triple/Vierfach/Vierfach/usw.)
Die folgende Tabelle gibt 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 |
Gleicher Origin | Nur der Pfad unterscheidet sich |
http://store.company.com/dir/inner/another.html |
Gleicher Origin | Nur der Pfad unterscheidet sich |
https://store.company.com/page.html |
Unterschiedlicher Origin | Unterschiedliches Protokoll |
http://store.company.com:81/dir/page.html |
Unterschiedlicher Origin | Unterschiedlicher Port (http:// ist standardmäßig Port 80) |
http://news.company.com/dir/page.html |
Unterschiedlicher Origin | Unterschiedlicher Host |
Geerbte Origins
Skripte, die von Seiten mit einer about:blank
oder 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.
Zum Beispiel wird about:blank
oft als URL für neue, leere Pop-up-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 Origin erben wie das Skript, das es erstellt hat.
data:
URLs erhalten einen neuen, leeren Sicherheitskontext.
Datei-Origins
Moderne Browser behandeln in der Regel den Origin von Dateien, die mit dem file:///
-Schema geladen werden, als undurchsichtige Origins.
Das bedeutet, dass, wenn eine Datei andere Dateien aus demselben Ordner einbindet, sie nicht als vom selben Origin angenommen werden und möglicherweise CORS-Fehler ausgelöst werden.
Beachten Sie, dass die URL-Spezifikation angibt, dass der Origin von Dateien implementierungsabhängig ist, und einige Browser Dateien im gleichen Verzeichnis oder Unterverzeichnis als gleichen Origin betrachten können, auch wenn dies Sicherheitsimplikationen hat.
Änderung des Origin
Warnung:
Die hier beschriebene Methode (Verwendung des document.domain
-Setters) ist veraltet, da sie die durch die Same-Origin-Policy bereitgestellten Sicherheitsmechanismen untergräbt und das Origin-Modell in Browsern kompliziert, was zu Interoperabilitätsproblemen und Sicherheitslücken führt.
Eine Seite kann ihren eigenen Origin ändern, jedoch mit einigen Einschränkungen. 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 wird, wird die kürzere Superdomain für Same-Origin-Prüfungen verwendet.
Zum Beispiel, nehmen wir an, ein Skript aus dem Dokument unter http://store.company.com/dir/other.html
führt Folgendes aus:
document.domain = "company.com";
Danach kann die Seite die Same-Origin-Prüfung 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). 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
, verursacht, 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 einen SecurityError
DOMException
auslösen, wenn das Dokument in einem sandboxed <iframe>
ist, und die Änderung des Origin auf diese Weise beeinflusst nicht die Origin-Prüfungen, die von vielen Web-APIs verwendet werden (z. B. localStorage
, indexedDB
, BroadcastChannel
, SharedWorker
). Eine detailliertere Liste von Fehlerfällen finden Sie unter Document.domain > Failures.
Hinweis:
Wenn Sie document.domain
verwenden, um einem Subdomain Zugriff auf sein Parent zu gewähren, müssen Sie document.domain
auf den gleichen Wert sowohl im Parent-Domain als auch im Subdomain setzen. Dies ist notwendig, selbst wenn Sie dadurch die Parent-Domain auf ihren ursprünglichen Wert zurücksetzen. Ein Versäumnis dessen kann zu Berechtigungsfehlern führen.
Netzwerk-Zugriff über unterschiedliche Origins
Die Same-Origin-Policy kontrolliert Interaktionen zwischen zwei verschiedenen Origins, wie wenn Sie fetch()
oder ein <img>
-Element verwenden. Diese Interaktionen werden typischerweise in drei Kategorien eingeteilt:
- Cross-Origin Writes sind in der Regel erlaubt. Beispiele sind Links, Weiterleitungen und Formularübermittlungen. Einige HTTP-Anfragen erfordern Preflight.
- Cross-Origin Embedding ist in der Regel erlaubt. (Beispiele sind unten aufgeführt.)
- Cross-Origin Reads sind in der Regel nicht erlaubt, aber Lesezugriff wird oft durch Einbettung geleakt. Zum Beispiel können Sie die Dimensionen eines eingebetteten Bildes, die Aktionen eines eingebetteten Skripts oder die Verfügbarkeit einer eingebetteten Ressource lesen.
Hier sind einige Beispiele für Ressourcen, die Cross-Origin eingebettet werden können:
- JavaScript mit
<script src="…"></script>
. Fehlermeldungen für Syntaxfehler sind nur für same-origin Skripte verfügbar. - CSS angewendet mit
<link rel="stylesheet" href="…">
. Aufgrund der entspannten Syntaxregeln von CSS erfordert Cross-Origin-CSS einen korrektenContent-Type
-Header. Browser blockieren das Laden von Stylesheets, wenn es sich um ein Cross-Origin-Load handelt, bei dem 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>
. - Schriften angewendet mit
@font-face
. Einige Browser erlauben Cross-Origin-Schriften, andere erfordern Same-Origin. - Alles, was mit
<iframe>
eingebettet wird. Websites können denX-Frame-Options
Header verwenden, um Cross-Origin-Framing zu verhindern.
Anleitung zur Erlaubnis von Cross-Origin-Zugriff
Verwenden Sie CORS, um Cross-Origin-Zugriff zu erlauben. CORS ist ein Teil von HTTP, der es Servern ermöglicht anzugeben, welche anderen Hosts das Laden von Inhalten durch den Browser erlauben sollten.
Anleitung zur Blockierung von Cross-Origin-Zugriff
- Um Cross-Origin Writes zu verhindern, überprüfen Sie ein nicht erratbares Token in der Anfrage — bekannt als Cross-Site Request Forgery (CSRF) Token. Sie müssen Cross-Origin Reads von Seiten verhindern, die dieses Token erfordern.
- Um Cross-Origin Reads einer 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 Cross-Origin Embeds zu verhindern, stellen Sie sicher, dass Ihre Ressource nicht als eines der oben aufgeführten einbettbaren Formate interpretiert werden kann. Browser können den
Content-Type
Header möglicherweise nicht respektieren. Wenn Sie zum Beispiel ein<script>
-Tag auf ein HTML-Dokument zeigen, wird der Browser versuchen, das HTML als JavaScript zu parsen. Wenn Ihre Ressource kein Einstiegspunkt zu Ihrer Site ist, können Sie auch ein CSRF-Token verwenden, um das Einbetten zu verhindern.
Cross-Origin-Skript-API-Zugriff
JavaScript-APIs wie iframe.contentWindow
, window.parent
, window.open
und window.opener
erlauben Dokumenten, sich direkt zu referenzieren. Wenn zwei Dokumente nicht denselben Origin haben, bieten diese Referenzen nur sehr begrenzten Zugriff auf Window
und Location
-Objekte, wie in den nächsten zwei Abschnitten beschrieben.
Um zwischen Dokumenten aus verschiedenen Origins zu kommunizieren, verwenden Sie window.postMessage
.
Spezifikation: HTML Living Standard § Cross-Origin-Objekte.
Fenster
Der folgende Cross-Origin-Zugriff 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.
Standort
Der folgende Cross-Origin-Zugriff auf Location
-Eigenschaften ist erlaubt:
Methoden |
---|
location.replace |
Attribute | |
---|---|
location.href |
Nur schreibgeschützt. |
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 Origin getrennt. Jeder Origin erhält seinen eigenen separaten Speicher, und JavaScript in einem Origin kann nicht aus dem Speicher eines anderen Origins lesen oder in ihn 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 öffentliche Suffix ist. Firefox und Chrome verwenden die Public Suffix List, um zu bestimmen, ob eine Domain ein öffentliches Suffix ist. Wenn Sie ein Cookie setzen, können Sie seine Verfügbarkeit mit den Domain
, Path
, Secure
und HttpOnly
Flags 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.