Neue Methoden für Cross-Origin Isolation: Resource, Opener & Embedding Policies mit COOP, COEP, CORP und CORB

This document sat in my archives. I originally created this so I have notes for my participation in the Working Draft podcast - a German podcast for web developers. That's why this article is in German as well. The podcast episode 452 was published in 2020, but I never published this document. In the interest of breathing some live into this blog, here it is. Have fun!

Hintergrund: CORS & Same-Origin Policy

Die erste und wichtigste Grundregel in Sachen Web- & Browser-Sicherheit ist die Same-Origin Policy. Sie bestimmt, dass alle Webseiten im gleichen Origin auch mit den gleichen Rechten ausgestattet sind. Ein Origin ist das Tripel von "Scheme, Host, Port".

Das bedeutet insbesondere, dass JavaScript keinen Zugriff auf Inhalte aus anderen Origins erhält.

Wenn man also ein Bild, iframe oder Popup von einem anderen Origin lädt, dann kann man es zwar darstellen lassen, aber eben nicht per JavaScript auslesen. Egal ob via canvas, iframe.contentDocument, popup.contentDocument usw.

Wichtig ist noch zu erwähnen, dass hier etwas namens "ambient authority" greift: Wenn ein iframe von, sagen wir mal twitter.com (z.B. ein Tweet-Knopf) angezeigt wird, schickt der Browser die Cookies für twitter.com mit, so dass Twitter die Antwort auf den aktuellen Account des aktuellen Benutzers anpassen kann.

Eine Ausnahme bietet hier CORS, das Cross-Origin Resource Sharing. Eine Seite kann explizit erlauben, von anderen Origins gelesen zu werden, wenn sie in dem Response Header eine entsprechende Erlaubnis per CORS. Der häufigste header im Response lautet

Access-Control-Allow-Origin: *, damit sind alle Webseiten erlaubt, die Datei zu laden UND auszulesen.

Wenn man möchte, kann man hier noch zwischen anonymen und credentialed requests unterscheiden:

Mit dem * im ACAO-Header wird jedem das Lesen erlaubt. Das besondere am * ist, dass implizit nur anonyme Requests erlaubt werden.

Probleme die Same-Origin Policy und CORS nicht lösen

Die Same-Origin Policy ist eine mächtige, allgegenwärtige Maßnahme, lässt jedoch einige Probleme ungelöst.

XSLeaks

Der Angriff des sogenannten Cross-Site Leaks besteht schon seit gut 10 Jahren, ist aber kürzlich erneut in den Fokus gerückt. Ein xsleak-Angriff macht sich bestimmtes Browserverhalten (zum Beispiel) Timing zu nutze um Informationen über eine cross-origin Webseite zu erhalten. Ein ganz einfaches Beispiel ist eine Seite, die nur nach dem Login einen <iframe> anzeigt. Wenn ein Angreifer nun diese Seite selbst in ein <iframe> öffnet, kann der Angreifer über iframeEl.contentWindow.length herausfinden, ob die Seite weitere frames beinhält und somit deduzieren ob der Benutzer eingeloggt ist.

Natürlich wissen wir alle, dass es eine schlechte Idee ist, dem Angreifer zu erlauben unsere Seite in einem <iframe> zu öffnen, deswegen gibt es ja die CSP frame-ancestors direktive & X-Frame-Options.

Derselbe Angriff funktioniert nur leider ebenfalls mit einem Popup bzw der Referenz, die aus window.open fällt. Ferner lässt sich eben diese Schwachstelle nicht aufheben, da Browser hier die Rückwärtskompatibilität für existierende Webseiten wahren müssen.

Unter dem Begriff XSLeaks gibt es allerdings noch viele weitere Techniken:

  • history.length lässt sich benutzen um redirects zu erkennen (nützlich für Login detection in login_and_then-Patterns in Webseiten)

  • Bilder, Videos, Audio erlauben das ausmessen von metadaten (A/V-Länge, Bilddimensionen)

  • Request timing (wie lange dauert ein fetch())

  • Leak of HTTP request done by exhausting the Network pool

Spectre

Anfang 2018 veröffentlichte eine Gruppe von Sicherheitsforschern die Sicherheitslücken Spectre & Meltdown. Diese Schwachstellen betreffen die gängigsten CPUs von u.a. AMD, Intel. Durch cleveres Ausnutzen einer Optimierung (speculative branching), die so vom Angreifer kontrolliert wird, dass sie nicht greift und eine "branch misprediction" rückgängig gemacht werden soll, ist es dem Angreifer möglich den gesamten Speicher innerhalb des selben laufenden Prozesses auszulesen. Ferner hat ein Team von Microsoft Vulnerability Research gezeigt, dass sich diese Lücke via JavaScript ausnutzen lässt.

Spectre ist insbesondere für Browser ein Problem, da sich mehrere Origins normalerweise einen Prozess teilen.

Diese Angriffe benötigen meist APIs für Shared Memory, wie SharedArrayBuffer. Daher haben sich die Browser darauf geeinigt SharedArrayBuffer vorübergehend abzuschalten.

Zusammenfassend: Sicherheitslücken vermeiden, Zugriff zu SharedArrayBuffer wieder erlangen:

Es gibt sinnige Bestrebungen, sich weiter von anderen Webseiten fernzuhalten, als nur durch die Same-Origin Policy forciert.

Informationen zu Fenstern aus anderen Origins können nicht vollständig aus dem jeweiligen Prozess rausgehalten werden, zum Beispiel durch <img src>.

Im Zuge dessen, sind Browser dazu übergegangen jedem Origin seinem eigenen Prozess zuzuweisen. Das nennen wir Site-Isolation bzw. bei Firefox "Project Fission".

Normalerweise würde der Browser ungefähr jedem Tab einen eigenen Prozess zuweisen. Mit "Site Isolation" benötigen wir für jeden iframe einen weiteren Prozess. Für eine News-Webseite wie cnn.com werden statt einem Prozess nun auf einmal etwa 14 Prozesse benötigt.

Neue Methoden für Cross-Origin Isolation

Aufgrund der neuen Angriffe und der neuen Browser-Architektur, ziehen es bestimmte Webseiten nun vor sich und ihr Origin komplett zu isolieren. Wenn man als Webseite in seinem komplett eigenen Tab ist - ohne Ausnahme, dann wäre auch ein Spectre-Angriff nicht mehr problematisch. Alles was ausgelesen werden kann, ist ohnehin eigene Information. Um das zu ermöglichen, wurden ein paar neue Sicherheitsmechanismen in Form eines HTTP Response Headers eingeführt. Eine Kombination derer erlaubt es, als "crossOriginIsolated" zu gelten und somit wieder Zugriff auf SharedArrayBuffer zu erhalten.

Hier nun ein kurzer Überblick über die neuen Cross-Origin primitiven:

Cross-Origin-Opener-Policy (COOP)

Cross-Origin-Opener-Policy: unsafe-none | same-origin-allow-popups | same-origin

Unter Zuhilfenahme von Cross-Origin-Opener-Policy, kann eine Seite explizit sagen, dass es keine window-handles (opener, popup) für Fenster aus anderen Origins geben darf:

Hierfür senden wir Cross-Origin-Opener-Policy: same-origin.

Cross-Origin-Embedder-Policy (COEP)

Cross-Origin-Embedder-Policy: unsafe-none | require-corp | credentialless

Wenn man COOP einsetzt besteht immer noch die Möglichkeit, dass man selbst noch irgendwelche Cross-Origin Resourcen nachlädt (versehentlich, redirects, usw.). Mit Cross-Origin-Embedder-Policy: require-corp kann man sicher stellen, dass das Dokument nur Ressourcen in den Prozess lädt, die von dem eigenen Origin sind oder es explizit erlaubt (durch CORP. siehe unten) .

Wenn der Wert credentialless gesetzt ist, werden cross-origin Inhalte ohne Cookies (credentials) angefordert. Das erlaubt Interaktionen mit Webseiten, die nicht explizit "CORP" benutzen.

COOP + COEP = crossOriginIsolated

Nur wenn man COOP+COEP einsetzt, erhält eine Website das Attribut window.crossOriginIsolated als true. Nur, wenn man sich mit seinen eigenen (plus eventuell öffentlichen) Daten in einem eigenen Prozess abschottet, erhält man Zugriff auf SharedArrayBuffer und einen besonders genauen Timer in der Performance API.

CORP

Cross-Origin-Resource-Policy: same-site | same-origin | cross-origin

Mit CORP kann man, in etwa analog zu CORS, eine Ressource freischalten und für den Gebrauch als öffentlich jenseits der Prozessgrenzen hinweg deklarieren

CORB bzw. ORB

Im Gegensatz zu den letzt genannten Methoden sind CORB, ORB kein HTTP Header, sondern eine Festlegung, wie ein Browser gewisse Ressourcen zu laden hat:. Die Idee basiert darauf, dass cross-origin Resourcen mit "zweifelhaften Content-Typen" so blockiert werden, dass sie für den Webprozess als "Network Error" dargestellt werden. Weitestgehend, geht es darum Inhalte bereits an der Prozessgrenze zu blockieren, wenn nicht eindeutig klar ist, dass sie für den Gebrauch wirklich erlaubt sind. Typische Beispiele sind Inhalte mit Content-Type text/plain, welches dann über <script> geladen werden könnten und trotz Syntaxfehler im Prozessspeicher landen. Dies wird künftig nicht mehr möglich sein.

Ausblick

Da die Themen xsleaks und auch Spectre noch relativ jung sind, ist zu erwarten dass es weitere Mechanismen, Einschränkungen oder neue Werte für die hier vorgestellten Response Header entwickelt werden. Bereits jetzt werden Mechanismen wie "restrict-properties" für Cross-Origin-Opener Policy vorgeschlagen, was die Isolation beibehalten soll aber OAuth-Flows über pop ups ermöglichen könnte.

Es wird sich zeigen, was hier ausreichend ist und bleibt.


If you find a mistake in this article, you can submit a pull request on GitHub.

Other posts

  1. Prompt Injections and a demo (Wed 18 September 2024)
  2. The Mozilla Monument in San Francisco (Fri 05 July 2024)
  3. What is mixed content? (Sat 15 June 2024)
  4. How I got a new domain name (Sat 15 June 2024)
  5. How Firefox gives special permissions to some domains (Fri 02 February 2024)
  6. Examine Firefox Inter-Process Communication using JavaScript in 2023 (Mon 17 April 2023)
  7. Origins, Sites and other Terminologies (Sat 14 January 2023)
  8. Finding and Fixing DOM-based XSS with Static Analysis (Mon 02 January 2023)
  9. DOM Clobbering (Mon 12 December 2022)
  10. Neue Methoden für Cross-Origin Isolation: Resource, Opener & Embedding Policies mit COOP, COEP, CORP und CORB (Thu 10 November 2022)
  11. Reference Sheet for Principals in Mozilla Code (Mon 03 August 2020)
  12. Hardening Firefox against Injection Attacks – The Technical Details (Tue 07 July 2020)
  13. Understanding Web Security Checks in Firefox (Part 1) (Wed 10 June 2020)
  14. Help Test Firefox's built-in HTML Sanitizer to protect against UXSS bugs (Fri 06 December 2019)
  15. Remote Code Execution in Firefox beyond memory corruptions (Sun 29 September 2019)
  16. XSS in The Digital #ClimateStrike Widget (Mon 23 September 2019)
  17. Chrome switching the XSSAuditor to filter mode re-enables old attack (Fri 10 May 2019)
  18. Challenge Write-up: Subresource Integrity in Service Workers (Sat 25 March 2017)
  19. Finding the SqueezeBox Radio Default SSH Password (Fri 02 September 2016)
  20. New CSP directive to make Subresource Integrity mandatory (`require-sri-for`) (Thu 02 June 2016)
  21. Firefox OS apps and beyond (Tue 12 April 2016)
  22. Teacher's Pinboard Write-up (Wed 02 December 2015)
  23. A CDN that can not XSS you: Using Subresource Integrity (Sun 19 July 2015)
  24. The Twitter Gazebo (Sat 18 July 2015)
  25. German Firefox 1.0 ad (OCR) (Sun 09 November 2014)
  26. My thoughts on Tor appliances (Tue 14 October 2014)
  27. Subresource Integrity (Sun 05 October 2014)
  28. Revoke App Permissions on Firefox OS (Sun 24 August 2014)
  29. (Self) XSS at Mozilla's internal Phonebook (Fri 23 May 2014)
  30. Tales of Python's Encoding (Mon 17 March 2014)
  31. On the X-Frame-Options Security Header (Thu 12 December 2013)
  32. html2dom (Tue 24 September 2013)
  33. Security Review: HTML sanitizer in Thunderbird (Mon 22 July 2013)
  34. Week 29 2013 (Sun 21 July 2013)
  35. The First Post (Tue 16 July 2013)
π