504 Stimmen

Was ist das Motiv hinter der Einführung von Preflight-CORS-Anfragen?

Cross-origin resource sharing ist ein Mechanismus, der es einer Webseite ermöglicht, XMLHttpRequests zu einer anderen Domain zu machen (von Wikipedia).

Ich habe mich in den letzten Tagen mit CORS beschäftigt und ich denke, ich verstehe ziemlich gut, wie alles funktioniert.

Also meine Frage bezieht sich nicht darauf, wie CORS / Preflights funktionieren, sondern auf den Grund, warum Preflights als neuer Anforderungstyp eingeführt wurden. Ich sehe keinen Grund, warum Server A an Server B eine Preflight-Anfrage senden muss, nur um herauszufinden, ob die eigentliche Anfrage akzeptiert wird oder nicht - es wäre sicherlich möglich für B, RR ohne PR zu akzeptieren/abzulehnen.

Nachdem ich ziemlich viel gesucht habe, habe ich diesen Abschnitt an www.w3.org (7.1.5) gefunden:

Um Ressourcen vor Cross-Origin-Anfragen zu schützen, die von bestimmten Benutzeragenten stammen könnten, bevor diese Spezifikation existierte, wird eine Preflight-Anfrage gestellt, um sicherzustellen, dass die Ressource sich dieser Spezifikation bewusst ist.

Ich finde dies ist der schwerste Satz überhaupt zu verstehen. Meine Interpretation (sollte es besser 'bester Schuss' nennen) ist, dass es darum geht, Server B vor Anfragen von Server C zu schützen, die sich nicht der Spezifikation bewusst sind.

Kann mir jemand bitte ein Szenario erklären / ein Problem zeigen, das PR + RR besser löst als nur RR allein?

398voto

Michael Iles Punkte 4399

Ich habe einige Zeit damit verbracht, verwirrt über den Zweck der Preflight-Anfrage zu sein, aber ich glaube, ich habe es jetzt verstanden.

Der Schlüsselgedanke ist, dass Preflight-Anfragen keine Sicherheits-angelegenheit sind. Vielmehr handelt es sich um eine Regeländerung-angelegenheit.

Preflight-Anfragen haben nichts mit Sicherheit zu tun und haben keinen Einfluss auf Anwendungen, die derzeit mit Kenntnis von CORS entwickelt werden. Vielmehr profitiert der Preflight-Mechanismus von Servern, die ohne Kenntnis von CORS entwickelt wurden und dient als eine Art Realitätscheck zwischen Client und Server, um sicherzustellen, dass sie beide CORS-konform sind. Die Entwickler von CORS waren der Ansicht, dass es genügend Server gab, die sich auf die Annahme verließen, dass sie z.B. nie eine Cross-Domain-DELETE-Anfrage erhalten würden, und erfanden den Preflight-Mechanismus, um beiden Seiten eine Zustimmung zu ermöglichen. Sie waren der Meinung, dass die Alternative, nämlich einfach die Cross-Domain-Anfragen zu ermöglichen, zu vielen bestehenden Anwendungen führen würde, die dadurch beeinträchtigt worden wären.

Es gibt hier drei Szenarien:

  1. Alte Server, die nicht mehr entwickelt werden und die vor CORS entwickelt wurden. Diese Server könnten davon ausgehen, dass sie z.B. nie eine Cross-Domain-DELETE-Anfrage erhalten. Dieses Szenario ist der Hauptnutznießer des Preflight-Mechanismus. Ja, diese Dienste könnten bereits von einem böswilligen oder nicht konformen User-Agenten missbraucht werden (und CORS ändert daran nichts), aber in einer Welt mit CORS bietet der Preflight-Mechanismus einen zusätzlichen "Realitätscheck", damit Client und Server nicht aufgrund geänderter Webregeln ausfallen.

  2. Server, die noch entwickelt werden, aber die eine Menge alter Codes enthalten und für die es nicht machbar/wünschenswert ist, alle alten Codes zu überprüfen, um sicherzustellen, dass sie in einer Cross-Domain-Welt ordnungsgemäß funktionieren. Dieses Szenario ermöglicht es Servern, schrittweise auf CORS umzusteigen, z.B. indem sie sagen: "Jetzt erlaube ich diesen bestimmten Header", "Jetzt erlaube ich dieses bestimmte HTTP-Verb", "Jetzt erlaube ich Cookies/Auth-Informationen zu senden", usw. Dieses Szenario profitiert von dem Preflight-Mechanismus.

  3. Neue Server, die mit Kenntnis von CORS geschrieben sind. Gemäß den Standard-Sicherheitspraktiken muss der Server seine Ressourcen vor jeder eingehenden Anfrage schützen - Server können den Clients nicht vertrauen, keine böswilligen Aktionen durchzuführen. Dieses Szenario profitiert nicht vom Preflight-Mechanismus: Der Preflight-Mechanismus bietet einem Server, der seine Ressourcen ordnungsgemäß geschützt hat, keine zusätzliche Sicherheit.

367voto

Was war das Motiv für die Einführung von Vorfalldaten?

Vorfalldaten wurden eingeführt, damit ein Browser sicher sein konnte, dass er es mit einem CORS-fähigen Server zu tun hatte, bevor er bestimmte Anfragen sendete. Diese Anfragen wurden definiert als solche, die sowohl potenziell gefährlich (zustandsändernd) als auch neu waren (vor CORS aufgrund der Same Origin Policy nicht möglich). Die Verwendung von Vorfalldaten bedeutet, dass Server sich für die neuen, potenziell gefährlichen Arten von Anfragen, die CORS ermöglicht, freiwillig anmelden müssen (indem sie angemessen auf den Vorfalldaten antworten).

Das ist die Bedeutung von diesem Teil der ursprünglichen Spezifikation: "Um Ressourcen vor Cross-Origin-Anfragen zu schützen, die nicht von bestimmten Benutzeragenten stammen konnten, bevor diese Spezifikation existierte, wird eine Vorfaldatenanfrage gestellt, um sicherzustellen, dass die Ressource sich dieser Spezifikation bewusst ist."

Kannst du mir ein Beispiel geben?

Stellen wir uns vor, ein Browser-Benutzer ist bei seiner Bankwebsite A.com angemeldet. Wenn er auf die bösartige Seite B.com navigiert, enthält diese Seite einige Javascript-Codes, die versuchen, eine DELETE-Anfrage an A.com/account zu senden. Da der Benutzer bei A.com angemeldet ist, würde diese Anfrage, wenn sie gesendet würde, Cookies enthalten, die den Benutzer identifizieren.

Vor CORS hätte die Same Origin Policy des Browsers dies blockiert. Aber da der Zweck von CORS darin besteht, genau diese Art von Cross-Origin-Kommunikation zu ermöglichen, ist dies nicht mehr angemessen.

Der Browser könnte einfach die DELETE-Anfrage senden und den Server entscheiden lassen, wie damit umgegangen werden soll. Aber was ist, wenn A.com nicht mit dem CORS-Protokoll vertraut ist? Es könnte die gefährliche DELETE-Aktion durchführen. Es könnte angenommen haben, dass aufgrund der Same Origin Policy des Browsers eine solche Anfrage nie empfangen werden könnte, und würde daher nie gegen einen solchen Angriff geschützt worden sein.

Um solche nicht-CORS-fähigen Server zu schützen, verlangt das Protokoll vom Browser, zuerst eine Vorfalldatenanfrage zu senden. Diese neue Art von Anfrage ist etwas, auf das nur CORS-fähige Server richtig reagieren können, was es dem Browser ermöglicht zu wissen, ob es sicher ist, die tatsächliche DELETE-Anfrage zu senden.

Warum dieser ganze Aufwand für den Browser, kann der Angreifer nicht einfach eine DELETE-Anfrage von seinem eigenen Computer aus senden?

Sicher, aber eine solche Anfrage würde nicht die Cookies des Benutzers enthalten. Der Angriff, den dies verhindern soll, basiert darauf, dass der Browser Cookies (insbesondere Authentifizierungsinformationen für den Benutzer) für die andere Domain zusammen mit der Anfrage sendet.

_Das klingt nach Cross-Site Request Forgery, wo ein Formular auf der Seite B.com an A.com mit den Cookies des Benutzers gesendet und Schaden verursacht werden kann._

Das stimmt. Eine andere Möglichkeit, dies auszudrücken, ist, dass Vorfalldatenanfragen erstellt wurden, um die CSRF-Angriffsfläche für nicht-CORS-fähige Server nicht zu erhöhen.

Aber POST wird als Methode aufgelistet, sodass keine Vorfalldaten erforderlich sind. Das kann den Zustand ändern und Daten genauso wie ein DELETE löschen!

Das ist wahr! CORS schützt Ihre Seite nicht vor CSRF-Angriffen. Andererseits sind Sie auch ohne CORS nicht vor CSRF-Angriffen geschützt. Der Zweck von Vorfalldatenanfragen besteht nur darin, Ihre CSRF-Exposition auf das zu beschränken, was bereits in der Zeit vor CORS existierte.

Seufz. OK, ich akzeptiere widerstrebend die Notwendigkeit von Vorfalldatenanfragen. Aber warum müssen wir das für jede Ressource (URL) auf dem Server tun? Der Server handhabt CORS entweder oder nicht.

Bist du sicher? Es ist nicht ungewöhnlich, dass mehrere Server Anfragen für eine einzelne Domain bearbeiten. Beispielsweise könnte es der Fall sein, dass Anfragen an A.com/url1 von einem bestimmten Typ von Server behandelt werden und Anfragen an A.com/url2 von einem anderen Typ von Server behandelt werden. Im Allgemeinen kann der Server, der eine einzelne Ressource behandelt, keine Sicherheitsgarantien für alle Ressourcen auf dieser Domain geben.

Gut. Lassen Sie uns einen Kompromiss finden. Lassen Sie uns einen neuen CORS-Header erstellen, der es dem Server ermöglicht, genau anzugeben, für welche Ressourcen er sprechen kann, damit zusätzliche Vorfalldatenanfragen an diese URLs vermieden werden können.

Gute Idee! Tatsächlich wurde der Header Access-Control-Policy-Path für genau diesen Zweck vorgeschlagen. Letztendlich wurde er jedoch aus der Spezifikation herausgelassen, offensichtlich weil einige Server die URI-Spezifikation fehlerhaft implementiert hatten, sodass Anfragen an Pfade, die für den Browser sicher zu sein schienen, tatsächlich auf den fehlerhaften Servern unsicher waren.

War dies eine kluge Entscheidung, die Sicherheit vor Leistung priorisierte und es den Browsern ermöglichte, die CORS-Spezifikation sofort umzusetzen, ohne bestehende Server zu gefährden? Oder war es kurzsichtig, das Internet dazu zu verurteilen, Bandbreite und Latenzzeit zu verschwenden, nur um Fehler in einem bestimmten Server zu berücksichtigen zu einer bestimmten Zeit?

Die Meinungen dazu gehen auseinander.

Nun, zumindest werden Browser die Vorfalldienstanfrage für eine einzelne URL im Cache speichern, oder?

Ja. Aber wahrscheinlich nicht für sehr lange. In WebKit-Browsern beträgt die maximale Vorabcache-Zeit derzeit 10 Minuten.

Seufz. Nun, wenn ich weiß, dass meine Server CORS-fähig sind und daher nicht den Schutz von Vorfalldatenanfragen benötigen, gibt es eine Möglichkeit, sie zu umgehen?

Ihre einzige echte Option besteht darin sicherzustellen, dass Ihre Anfragen CORS-sichere Methoden und Header verwenden. Das könnte bedeuten, benutzerdefinierte Header auszulassen, die Sie sonst einschließen würden (wie X-Requested-With), den Content-Type zu ändern oder mehr.

Was auch immer Sie tun, müssen Sie sicherstellen, dass Sie angemessene CSRF-Schutzmaßnahmen haben, da CORS nicht alle unsicheren Anfragen blockiert. Wie es in der ursprünglichen Spezifikation heißt: "Ressourcen, für die einfache Anfragen eine Bedeutung haben andere als Abrufen, müssen sich vor Cross-Site Request Forgery schützen".

70voto

monsur Punkte 42927

Betrachten Sie die Welt der Cross-Domain-Anfragen, bevor CORS eingeführt wurde. Sie könnten ein Standardformular POST verwenden oder ein script oder ein image-Tag verwenden, um eine GET-Anfrage zu senden. Es war nicht möglich, andere Anfragen als GET/POST zu stellen, und es war nicht möglich, benutzerdefinierte Header bei diesen Anfragen auszugeben.

Mit der Einführung von CORS standen die Spezifikationsautoren vor der Herausforderung, einen neuen Cross-Domain-Mechanismus einzuführen, ohne die bestehende Semantik des Webs zu brechen. Sie entschieden sich dafür, Servern eine Möglichkeit zu geben, sich für einen neuen Anfragetyp zu entscheiden. Diese Entscheidung ist die Vorab-Anfrage (preflight request).

Also benötigen GET/POST-Anfragen ohne benutzerdefinierte Header keine Vorab-Anfrage, da diese Anfragen bereits vor CORS möglich waren. Aber jede Anfrage mit benutzerdefinierten Headern oder PUT/DELETE-Anfragen benötigen eine Vorab-Anfrage, da diese neu im CORS-Spezifikation sind. Wenn der Server nichts über CORS weiß, wird er ohne CORS-spezifische Header antworten und die eigentliche Anfrage wird nicht gestellt.

Ohne die Vorab-Anfrage könnten Server unerwartete Anfragen von Browsern erhalten. Dies könnte zu Sicherheitsproblemen führen, wenn die Server nicht auf diese Art von Anfragen vorbereitet waren. Die CORS-Vorab-Anfrage ermöglicht eine sichere Einführung von Cross-Domain-Anfragen im Web.

45voto

Kornel Punkte 94135

CORS ermöglicht es Ihnen, mehr Header und Methodentypen anzugeben als dies bisher mit cross-origin oder

möglich war.

Einige Server könnten (schlecht) geschützt worden sein mit der Annahme, dass ein Browser z.B. keine cross-origin DELETE Anfrage oder eine cross-origin Anfrage mit dem X-Requested-With Header stellen kann, sodass solche Anfragen "vertrauenswürdig" sind.

Um sicherzustellen, dass der Server wirklich CORS unterstützt und nicht nur zufällige Anfragen beantwortet, wird der Preflight ausgeführt.

20voto

Hirako Punkte 329

Ich habe das Gefühl, dass die anderen Antworten nicht darauf eingehen, warum die Sicherheit durch Pre-Flight verbessert wird.

Szenarien:

1) Mit Pre-Flight. Ein Angreifer fälscht eine Anfrage von der Website dummy-forums.com, während der Benutzer bei safe-bank.com angemeldet ist.
Wenn der Server nicht überprüft, woher die Anfrage stammt, und irgendeinen Fehler hat, wird der Browser eine Pre-Flight-Anfrage (OPTION-Methode) senden. Der Server weiß nichts von dem CORS, das der Browser als Antwort erwartet, also wird der Browser nicht weitermachen (kein Schaden).

2) Ohne Pre-Flight. Ein Angreifer fälscht die Anfrage unter dem gleichen Szenario wie oben, der Browser wird die POST- oder PUT-Anfrage sofort senden, der Server akzeptiert sie und könnte sie verarbeiten, was potenziell Schaden verursachen könnte.

Wenn der Angreifer eine Anfrage direkt, über Herkunftsgrenzen hinweg, von einem zufälligen Host sendet, ist es höchstwahrscheinlich, dass man an eine Anfrage ohne Authentifizierung denkt. Das ist eine gefälschte Anfrage, aber keine XSRF-Anfrage, daher wird der Server die Anmeldeinformationen überprüfen und ablehnen. CORS versucht nicht, einen Angreifer zu verhindern, der die Anmeldeinformationen hat, um Anfragen zu senden, obwohl eine Whitelist dazu beitragen könnte, diesen Angriffsvektor zu reduzieren.

Der Pre-Flight-Mechanismus trägt zur Sicherheit und Konsistenz zwischen Clients und Servern bei. Ich weiß nicht, ob es den zusätzlichen Handshake für jede Anfrage wert ist, da Caching dort kaum nutzbar ist, aber so funktioniert es.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X