Blog

Vorbehalte und Fallstricke bei Cookie-Domains

Cristiana

Cristiana

Aktualisiert Oktober 21, 2025
8 Minuten
Vor nicht allzu langer Zeit stießen wir bei meiner derzeitigen Aufgabe auf ein offensichtliches Sicherheitsproblem. Personen konnten sich mit einem normalen Konto anmelden, erhielten aber die Authentifizierung und die Berechtigungen eines Administratorbenutzers (ein Fehler bei der Privilegieneskalation). Wie sich herausstellte, waren die Auswirkungen des Sicherheitsproblems gering, da der Benutzer bereits als Administrator angemeldet sein musste, aber es war ein sehr verwirrendes Problem. In diesem Beitrag werde ich versuchen, die Situation zu erklären, wie Browser mit Wildcard-Subdomain-Cookies umgehen und was Sie beim Aufbau eines Authentifizierungs-Backends beachten sollten, wenn es um Cookies geht, die Sitzungsinformationen speichern. Zunächst einige Hintergrundinformationen. Wir betreiben eine Microservices-Architektur, bei der die Sicherheit über eine Art Authentifizierungsproxy gehandhabt wird. Jede Anfrage an einen Microservice durchläuft diesen Proxy, der ein vom Client gesendetes JWT-Token-Cookie überprüft. Wenn der Inhalt (ein base64-kodierter Satz von Schlüsseln/Werten, der Dinge wie Benutzer-ID, Berechtigungen usw. enthält) mit einer Signatur übereinstimmt (die von einem privaten Schlüssel im Authentifizierungsproxy signiert wurde), wird die Anfrage an den betreffenden Microservice weitergeleitet, angereichert mit einigen Headern, die die Authentifizierungsinformationen des Benutzers enthalten.Dieser Dienst kümmert sich auch um die Authentifizierung und verwaltet den Token-Cookie. Wenn ein Benutzer den Endpunkt mit einer Kombination aus Benutzername und Kennwort aufruft, ruft der Dienst seinerseits den Microservice für die Benutzerverwaltung auf, um den Benutzernamen und das Kennwort zu überprüfen. Wenn der Benutzerdienst ein OK zurückgibt, kodiert der Authentifizierungsdienst einige Benutzerinformationen (ID usw.) in ein JSON-Web-Token (JWT) -Cookie, signiert es und sendet es über einen -Header an den Client zurück.Aus Gründen, die die Zeit vergessen hat, hat das Token-Cookie ein -Attribut, das auf eine Wildcard-Subdomain gesetzt ist, die eine Ebene über dem Ursprung der Anfrage liegt. Das bedeutet, dass, wenn sich der Benutzer über anmeldet, das Attribut des Cookies auf gesetzt wird. Ich denke, dies sollte die gemeinsame Nutzung des Token-Cookies zwischen verschiedenen Entwicklungszweigen der Anwendung ermöglichen. Unsere Entwicklungsumgebung wird über URLs mit einem Muster von z.B. some-feature.dev.example.com. Wenn sich der Benutzer also auf einer dieser Subdomains anmeldet, wird ein Token-Cookie für .dev.example.com gesetzt. Das Problem wurde nun offensichtlich, als unser Admin-Tool unter einer neuen Adresse verfügbar wurde - es wurde zum Äquivalent von admin.example.com. Dies war eine sekundäre Anwendung, die jedoch dasselbe Authentifizierungssystem verwendet. Sie sehen wahrscheinlich schon, worauf das hinausläuft. Wenn Sie sich bei admin.example.com anmelden, wird ein Token-Cookie mit den Informationen des Admin-Kontos mit der Domain .example.com gesetzt. Wenn Sie sich mit einem normalen, nicht-administrativen Konto bei some-feature.dev.example.com anmelden, passieren ein paar Dinge:
  • Das Token-Cookie für .example.com, das die Informationen des Administrators enthält, würde zusammen mit dem Authentifizierungsaufruf des regulären Benutzers gesendet werden. Dies hat keine Fehler ausgelöst.
  • Wenn die Anmeldedaten des regulären Benutzers in Ordnung waren, würde der Authentifizierungsaufruf ein neues Token für .dev.example.com zurückgeben, das die Informationen für diesen Benutzer enthält. Damit wurde das Token mit dem weniger spezifischen Attribut Domain, wie in RFC 6265, Abschnitt 4.1.2 beschrieben, nicht überschrieben.
  • Alle nachfolgenden Aufrufe an das Backend würden zwei Token-Cookies enthalten, eines für .dev.example.commit dem JWT-Token des normalen Benutzers und eines für .example.com mit dem Token des Administrators.
Wir entdeckten dies hauptsächlich dadurch, dass ein Benutzername als angemeldet angezeigt wurde, die von den APIs zurückgegebenen Informationen jedoch zu einem Admin-Benutzer gehörten. Wir fanden heraus, dass das Token des Administrators zurückgegeben wurde, indem wir den zweiten Teil des JWT-Tokens durch einen base64-Decoder zogen - beachten Sie, dass JWT-Tokens base64-kodiert und signiert sind, nicht verschlüsselt. Dieses Problem war auch deshalb verwirrend, weil der Benutzername, der auf der Seite als angemeldeter Benutzer angezeigt wurde, der normale, nicht-administrative Benutzer war. Dieser Name wurde durch den Aufruf des Authentifizierungsendpunkts zurückgegeben und nicht allein auf der Grundlage des Tokens vom Server geholt. Diese Informationen wurden auch im lokalen Speicher abgelegt, so dass eine Aktualisierung die Informationen nicht aktualisierte.Das Back-End hat ein Szenario mit mehreren Cookies mit demselben Namen nie in Betracht gezogen. Abschnitt 4.2.2 von RFC 6265 verbietet zwar nicht mehrere Cookies mit demselben Namen, aber er besagt auch, dass der Server keine Annahmen über die Reihenfolge machen kann und dass keine Metadaten wie Domäne, Ablaufdatum, das Sicherheitsflag oder ähnliches mitgeschickt werden. Daher ist es ziemlich willkürlich, welches Token verwendet wurde, und daher, da es für die Authentifizierung verwendet wird, unsicher.Dieses Problem betrifft sowohl Chrome als auch Firefox, obwohl es bei letzterem etwas schwieriger zu beheben ist. Die Registerkarte in den Entwicklungstools von Chrome zeigt sowohl die Cookies als auch an, aber Firefox scheint nur das Cookie anzuzeigen, nachdem Sie sich bei der Entwicklungsanwendung angemeldet haben. Die eigentlichen Anfragen enthalten jedoch beide Cookies, also vertrauen Sie nicht zu sehr auf die Registerkarte "Speicher" von Firefox - ich würde sagen, dass es sich hier um einen Fehler handelt, den ich irgendwo melden sollte.Die schnelle Lösung war einfach genug; immer wenn zwei Token in einer Anfrage auftauchen, sagt der Authentifizierungsdienst "Ich weiß nicht, lol ¯_(ãƒ")_/¯" und gibt einen 401 Unauthorized zurück. Dies bringt den Benutzer jedoch in eine ungewisse Situation. Die aktuelle Front-End-Anwendung leitet den Benutzer bei Erhalt einer 401 auf eine Fehlerseite um; dies löst einen DELETE-Aufruf an den Endpunkt authentication aus, der wiederum einen Set-Cookie Header zurückgibt, der das Token-Cookie des Benutzers zurücksetzt. Allerdings geschieht dies nur für die Subdomain-plus-one-Ebene, auf der sich der Benutzer gerade befindet, nicht für alle Domains. Wir haben versucht, dies zu implementieren, aber es scheint, dass das Senden mehrerer Set-Cookie Header mit demselben Namen von der Spezifikation nicht erlaubt ist, selbst wenn sie unterschiedliche Domain oder Path Attribute haben. Dies verursacht auch Probleme mit einer angemesseneren Lösung. Ein sehr unerwünschter Nebeneffekt der Speicherung eines Cookies mit einer Wildcard-Subdomain ist, dass das Cookie mit anderen Subdomains geteilt wird. In unserem Fall führen wir unsere Anwendung auf app.example.com aus, aber die Unternehmenswebsite unseres Arbeitgebers läuft auf www.example.com. Dies ist ein weiteres Sicherheitsproblem, bei dem Token-Cookies zu www.example.com durchsickern, ganz zu schweigen von allen anderen Subdomains - und die Website ist groß genug, dass wir nicht genau wissen, wer darauf Zugriff hat. Die angemessenere Lösung besteht darin, das Cookie nur auf die Subdomain festzulegen, die die Anfrage initiiert hat. Dazu wird einfach kein Domain -Attribut im Set-Token -Header gesendet; die Browser setzen das Cookie dann ohne Platzhalter auf application.example.com; das Token ist weder für Geschwister-Subdomains (www.example.com) noch für Sub-Subdomains (dev.application.example.com) verfügbar. Dies ist einfach zu implementieren, allerdings gibt es Benutzer, die noch das alte Subdomain-Token (.example.com) haben. Wenn diese sich mit dem neuen Domain Attribut anmelden, haben sie zwei Token-Cookies (application.example.com und .example.com), was den Fehler der Authentifizierung mit zwei Token-Cookies auslösen wird. Die saubere Lösung wäre, zwei Set-Cookie Header zurückzugeben, einen, der das neue Token auf die vollständige Domäne setzt, einen, der das alte Wildcard-Cookie zurücksetzt. Aber das ist nicht erlaubt. Was funktionieren würde, wäre, den Namen des Token-Cookies zumindest vorübergehend zu ändern, z.B. in token2. Das werden wir wahrscheinlich tun und vielleicht den alten Namen wiederherstellen, sobald alle alten Token-Cookies abgelaufen sind (das würde etwa eine Woche dauern). Der Nachteil dabei ist, dass alle Benutzer abgemeldet würden und sich erneut anmelden müssten. Ein anderer Ansatz wäre, eine 'Token-Version' in den Inhalt des JWT-Cookies aufzunehmen. Der Authentifizierungsdienst kann dann beide Token-Cookies dekodieren und prüfen, ob es eines mit der aktuellen Version gibt, und dann dieses verwenden, während das alte Cookie natürlich abläuft. Zusammenfassend haben wir also einige Lektionen gelernt:
  • Seien Sie vorsichtig mit Platzhalter-Subdomänen in Cookies. Ich würde empfehlen, sie erst gar nicht zu verwenden. Bevorzugen Sie Cookies mit vollständiger Domäne und setzen Sie sie ohne das Attribut . Wenn Sie eine einmalige Anmeldung für Entwicklungszwecke erstellen möchten, gibt es bessere Möglichkeiten.
  • Sie können nicht mehrere Set-Cookie Kopfzeilen mit demselben Namen in einer Antwort senden.
  • Sie können die Domäne eines (Platzhalter-/Subdomänen-)Cookies mit demselben Namen praktisch nicht ändern.
  • Die Entwicklungstools in Chrome und Firefox geben die Cookies für die aktuelle Domain unterschiedlich an. Vertrauen Sie nicht auf die Registerkarten Storage in den Entwicklungstools der beiden Browser, sondern sehen Sie sich die tatsächlich gesendeten Cookie Anfrage-Header an. (Es wäre schön, wenn die Entwicklungstools diese besser lesbar formatieren würden)
  • Der Inhalt eines JWT-Tokens ist nicht verschlüsselt, sondern nur base64-kodiert und signiert. Speichern Sie keine kritischen Informationen wie Passwörter in einem JWT-Cookie.
  • Benutzerdaten sollten nach Möglichkeit nicht in einem lokalen Speicher abgelegt werden, nicht, wenn sie von einem Token abhängen, das sich ändern, widerrufen werden kann usw. Im Gegensatz zu Cookies hat der lokale Speicher auch kein Verfallsdatum, so dass er bestehen bleibt, bis er explizit gelöscht wird.
  • Wenn Sie ein Domain -Attribut auf die exakte Subdomain setzen (z.B. application.example.com), interpretiert Ihr Browser es dennoch als Platzhalter, so dass das Cookie für die Subdomain und alle ihre Subdomains gültig ist (d.h. es wird als .application.example.com angezeigt und ist für dev.application.example.com und weitere verfügbar). Senden Sie kein Domain -Attribut, um es auf die (Sub-)Domain zu beschränken und nichts anderes.
Hinweis: Dieser Artikel wurde von meiner persönlichen Website aus gepostet.

Verfasst von

Cristiana

Some bio goes here

Contact

Let’s discuss how we can support your journey.