CORS: Cross-Origin Resource Sharing erklärt
Eigentlich strengstens verboten: Wer eine Website aufruft, der soll keine zusätzlichen Daten von fremden Servern laden! Doch es kann Ausnahmen geben. Wenn beide Website-Betreiber sich über die Zusammenarbeit einig sind, spricht nichts gegen ein Abkommen. Das Cross-Origin Resource Sharing (CORS) regelt die Kooperation. Wie funktioniert das?
Wie funktioniert CORS?
Die Same-Origin-Policy (SOP) verbietet beim Besuch einer Website das Nachladen von anderen Servern. Alle Daten sollen von der gleichen Quelle kommen, also dem gleichen Server entspringen. Das ist eine Sicherheitsmaßnahme, denn JavaScript und CSS könne ohne das Wissen der Nutzer Inhalte von anderen Servern laden – auch schädliche Inhalte. Ein solcher Zugriffsversuch wird als Cross-Origin-Request bezeichnet. Ist aber beiden Websitebetreibern der Datenaustausch bekannt und von diesen auch gewünscht, kann man den Vorgang erlauben. Der angefragte Server – also der, von dem Inhalte nachgeladen werden sollen – erlaubt den Zugriff dann per Cross-Origin Resource Sharing.
Dies geschieht allerdings immer nur für bestimmte Clients. Das heißt: CORS ist kein Freibrief für jegliche Cross-Origin-Requests. Stattdessen erlaubt der zweite Server dem ersten per HTTP-Header den exklusiven Zugriff. In dem Kopf der HTTP-Antwort ist genau beschrieben, welche Server die Daten nachladen und dem Nutzer schließlich zur Verfügung stellten dürfen. Nur durch die Einbindung von Wildcards ist eine generelle Erlaubnis zum Zugriff durch alle Clients erlaubt. Dies ist aber nur sinnvoll für Server, die solche Informationen anbieten, die für die Allgemeinheit zur Verfügung stehen sollen – Web-Schriftarten beispielsweise.
Der Nutzer bekommt von dem Austausch der beiden beteiligten Server im besten Fall nichts mit. Alle aktuellen Browser unterstützen CORS, und das Senden von Anfragen und Antworten geschieht beim Aufruf einer Website innerhalb kürzester Zeit im Hintergrund.
Aufbau der CORS-Header
Im Sinne der Same-Origin-Policy bestehen bei einer Serververbindung die Angaben zur Herkunft aus drei Elementen: Host, Port und Protokoll. Die Richtlinie verbietet demnach, dass im obigen Beispiel "https://example.com" auf "http://example.com" oder auf "https://example.org" zugreift. Im ersten Fall ist das Protokoll nicht das gleiche, im zweiten sind die beiden Host-Angaben nicht identisch.
Bei einem Cross-Origin-Request handelt es sich im Prinzip um einen HTTP-Request. Bestimmte Methoden stellen grundsätzlich keine Probleme dar. GET und HEAD können Daten nicht ändern und werden deshalb in der Regel nicht als Sicherheitsrisiko wahrgenommen. Anders sieht es bei PATCH, PUT oder DELETE aus: Hiermit ist es möglich, schädliche Eingriffe vorzunehmen. Deshalb muss hierfür auch Cross-Origin Resource Sharing aktiviert werden. Demnach kann CORS nicht nur Informationen zum erlaubten Ursprung beinhalten, sondern auch darüber, welche HTTP-Requests durch die Quelle erlaubt sind.
Handelt es sich um sicherheitsrelevante HTTP-Methoden, sendet der Client zunächst eine Preflight-Anfrage. In dieser gibt man eigentlich nur an, welche HTTP-Methode man als nächstes an den Server richten wird und erfragt, ob die Anfrage als sicher gewertet wird. Dafür verwendet man den OPTIONS-Header. Erst nach einer positiven Rückantwort kann dann die eigentliche Anfrage gestellt werden.
Es gibt verschiedene CORS-Header, die sich jeweils mit unterschiedlichen Aspekten auseinandersetzen. Genannt wurden schon die beiden wichtigen Header zur Bestimmung von sicheren Ursprüngen und erlaubten Methoden. Aber es gibt noch weitere:
- Access-Control-Allow-Origin: Welche Herkunft ist erlaubt?
- Access-Control-Allow-Credentials: Sind Anfragen auch dann erlaubt, wenn der Credentials Mode auf include gesetzt ist?
- Access-Control-Allow-Headers: Welche Header dürfen verwendet werden?
- Access-Control-Allow-Methods: Welche HTTP-Request-Methoden sind erlaubt?
- Access-Control-Expose-Headers: Welche Header dürfen angezeigt werden?
- Access-Control-Max-Age: Wie alt darf die Preflight-Anfrage sein, bevor sie ihre Gültigkeit verliert?
- Access-Control-Request-Headers: Welcher HTTP-Header ist in der Preflight-Anfrage angegeben?
- Access-Control-Request-Method: Welcher HTTP-Methode ist in der Preflight-Anfrage angegeben?
- Origin: Was ist die Quelle der Anfrage?
Der besondere Fokus liegt auf dem ersten Header. Dort spezifiziert der Server, welcher andere Host auf ihn zugreifen darf. Neben einer konkreten Adresse kann man dort auch eine Wildcard in Form eines Asterisks angeben. Damit erlaubt der Server Cross-Origin-Requests von jeglichen Quellen.
Beispiel von Cross-Origin Resource Sharing
In unserem nachfolgenden Beispiel nehmen wir nun an, Host A (example.com) möchte einen DELETE-Request an Host B (example.org) senden. Dafür schickt der ursprüngliche Server zunächst eine Preflight-Anfrage:
/OPTIONS
Origin: http://example.com
Access-Control-Request-Method: DELETE
Hat Host B kein Problem mit diesem Cross-Origin-Request, antwortet er mit den entsprechenden CORS-Headern:
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: PUT, POST, DELETE
Stimmen die Header in der Antwort nicht mit den Spezifikationen der Anfrage überein oder antwortet der angefragte Server nicht, kann kein Cross-Origin-Request durchgeführt werden.
Vor- und Nachteile von CORS
Eigentlich dient CORS dazu, eine an sich sichere Grundeinstellung – nämlich die Same-Origin-Policy – zu umgehen. Die SOP ist wiederum ein wirksames Mittel, um potenziell gefährliche Verbindungen zu unterbinden. Das Internet basiert aber vielfach auf eben solchen Cross-Origin-Requests, denn viele Verbindungen von einem Host zum anderen sind durchaus gewünscht.
CORS bietet somit einen Zwischenweg: Für solche Situationen, bei denen Cross-Origin-Requests explizit benötigt werden, lassen sich durch CORS Ausnahmen schaffen. Allerdings besteht die Gefahr, dass Website-Betreiber aus Gründen der Bequemlichkeit nur auf Wildcards setzen. Dadurch würde man tatsächlich jeglichen Schutz durch die SOP negieren. Deshalb ist es wichtig, CORS nur in ausgewählten Sonderfällen einzusetzen und so restriktiv wie möglich zu konfigurieren.