OpenReception
Host-Header-Injection in Bestätigungsmails
generateBaseUrl baut den Konto-Bestätigungslink aus dem Host-Header der Anfrage, ohne Allowlist. Der nicht authentifizierte POST /api/auth/resend-confirmation rotiert das Bestätigungs-Token einer noch nicht bestätigten eingeladenen Person und versendet einen Link, dessen Host aus der Anfrage stammt, sodass ein gefälschter Host den Bestätigungslink auf eine angreiferkontrollierte Domain umlenkt. Folgt die Person dem Link, erreicht das Einmal-Token den Angreifer, der das Konto übernehmen kann, bevor die eingeladene Person es jemals nutzt. Der zugehörige Einladungspfad baut Links bereits aus der vertrauenswürdigen tenant.domain; dieser Pfad nicht. Alle Releases bis einschließlich 1.1.1 sind betroffen; behoben in 2.0.0.
Beschreibung
OpenReception ist eine selbst gehostete, mandantenweise Terminbuchung für Arztpraxen mit Ende-zu-Ende-Verschlüsselung zwischen Clients und Mitarbeitern. Mitarbeiter und Mandanten-Administratoren treten über eine Einladung bei, die sie durch Aufruf eines per E-Mail zugesandten Einmal-Links bestätigen. Wir schätzen die Arbeit des Projekts an einem datenschutzfreundlichen Buchungsdesign und das Engagement der Maintainer bei diesem Report.
Der Host des Bestätigungslinks stammt aus der Anfrage. generateBaseUrl gibt Protokoll, Hostname und Port der Anfrage-URL zurück, ohne Allowlist:
src/lib/server/email/email-service.ts:402-407
export function generateBaseUrl(url: URL): string { const protocol = url.protocol; const port = url.port ? `:${url.port}` : ""; const hostname = url.hostname; return `${protocol}//${hostname}${port}`;}sendConfirmationEmail baut den Bestätigungslink daraus: const confirmUrl = generateBaseUrl(requestUrl) + "/confirm/" + confirmationCode.
Der Endpunkt, der diese E-Mail auslöst, ist nicht authentifiziert und reicht den Host der Anfrage weiter. POST /api/auth/resend-confirmation nimmt nur eine E-Mail-Adresse entgegen und gibt die Anfrage-url unverändert weiter:
src/routes/api/auth/resend-confirmation/+server.ts:71-76
export const POST: RequestHandler = async ({ request, url }) => { const body = await request.json(); await UserService.resendConfirmationEmail(body.email, url); // ...};UserService.resendConfirmationEmail rotiert den Einladungscode des noch nicht bestätigten Kontos auf ein frisches, zehn Minuten gültiges Token und versendet anschließend den aus dieser Anfrage-url gebauten Link. Die Suche in der zentralen Datenbank erfolgt über die E-Mail-Adresse; ein gefälschter Host ändert daher nur den Host im erzeugten Link, nicht das adressierte Konto. Ein gefälschter Host mit der E-Mail-Adresse einer eingeladenen Person liefert somit eine Bestätigungsmail, deren Bestätigungslink https://attacker.example/confirm/<token> lautet.
Der zugehörige Einladungspfad baut seinen Link in der Produktion aus der vertrauenswürdigen tenant.domain (invite/+server.ts:209); resend-confirmation übergibt die rohe Anfrage-url an generateBaseUrl, sodass dieselbe vertrauenswürdige Domain-Quelle nicht genutzt wird. Dies ist von CVE-2026-48081 zu unterscheiden, das einen javascript:-Link in der E-Mail-Fußzeile betraf; es handelt sich um ein eigenständiges Verhalten im selben E-Mail-Pfad.
Ob ein gefälschter Host die Anwendung erreicht, hängt vom vorgelagerten Proxy ab. Die Standard-docker-compose.prod.yml setzt kein ORIGIN, und das mitgelieferte Caddyfile stellt der App einen :443-Catch-all voran (reverse_proxy app:3000, On-Demand-TLS). Der Catch-all ergibt sich aus dem dynamischen Mandantenmodell: Mandanten fügen eigene Domains hinzu und Caddy stellt Zertifikate auf Anforderung aus, sodass der vorgelagerte Block die Mandanten-vHosts nicht statisch aufzählen kann. Ein Catch-all reicht einen beliebigen Host standardmäßig nach oben weiter, und Caddy bindet den Host nicht an die TLS-SNI; eine Anfrage, die TLS mit einer gültigen Mandanten-SNI aushandelt und dann einen gefälschten Host trägt, erreicht die App mit dem Angreifer-Host. Dieser Zustellweg ist aus dem mitgelieferten Caddyfile und dem Standardverhalten von reverse_proxy abgeleitet; der Proof of Concept richtet sich direkt an die Anwendung und übt die Proxy-Schicht nicht aus.
Ein Betreiber, der den Proxy stattdessen mit expliziten Blöcken pro Mandant und ohne Catch-all konfiguriert, macht den Proxy zu einer Host-Allowlist und ist nicht betroffen; diese Konfiguration ist mit dem On-Demand-Mandanten-Domain-Feature unvereinbar und nicht die Standardeinrichtung.
Sobald der Angreifer das Einmal-Token besitzt, wird das Konto über den eigenen Bestätigungs- und Passkey-Registrierungs-Flow der Anwendung auf der echten Mandanten-Domain beansprucht, die der Angreifer normal erreicht. Der Angreifer registriert einen selbst kontrollierten Passkey und meldet sich an, womit er eine vollständige Session als die eingeladene Person erhält, bevor diese das Konto jemals genutzt hat. Der Login-Schritt fälscht nichts: Nur die resend-confirmation-Anfrage trägt den gefälschten Host.
Auswirkung
- Der Angriff setzt voraus, dass die betroffene Person eine noch nicht bestätigte eingeladene Person ohne registrierten Passkey ist, die dem zugesandten Link folgt, auf einer Instanz, deren vorgelagerter Proxy den gefälschten
Hostweiterreicht (der Standard-Catch-all tut dies). Unter diesen Bedingungen übernimmt ein Angreifer das Konto der eingeladenen Person in der Rolle, mit der sie eingeladen wurde. Realistisches Ziel ist eine Staff- oder Tenant-Admin-Einladung mitten im Onboarding: Das vorherige Beanspruchen des Kontos und das Registrieren eines angreiferkontrollierten Passkeys verschafft dem Angreifer an ihrer Stelle eine vollständige Session. Aus dieser Session hält der Angreifer die Berechtigungen der eingeladenen Person über den Mandanten, was bei einem Staff-Konto die Termindaten des Mandanten und das nur Mitarbeitern zugängliche Verzeichnis umfasst, auf das die Rolle zugreifen kann. - Betroffen sind der eingeladene Mitarbeiter, dessen Konto übernommen wird, bevor er es jemals nutzt, sowie die Klienten der Praxis, deren Termindatensätze die übernommene Session lesen und je nach Rolle stornieren, ändern oder löschen kann. Der angreiferkontrollierte Link kommt in einer routinemäßigen Onboarding-Mail an, die der eigene Server der Praxis von seiner gewohnten Absenderadresse erzeugt, sodass die eingeladene Person kaum Anhaltspunkte für Misstrauen hat.
Abhilfe
Aktualisieren Sie auf OpenReception 2.0.0, das dieses Advisory behebt; 2.0.0 ist ein Major-Release, das eine erforderliche MANAGEMENT_DOMAIN-Umgebungsvariable einführt, prüfen Sie daher vor dem Update die Release Notes. Der zugrunde liegende Fix baut den Bestätigungslink aus einer vertrauenswürdigen Domain statt aus dem Host der Anfrage, wie es der Einladungspfad bereits tut (invite/+server.ts:209); ein einzelnes ORIGIN passt nicht sauber zu einer Multi-Domain-, Multi-Mandanten-Bereitstellung. Als zusätzliche Schutzschicht kann der vorgelagerte Proxy so konfiguriert werden, dass er nur bekannte Host-Werte nach oben weiterreicht, was jedoch mit On-Demand-Mandanten-Domains unvereinbar und daher der anwendungsseitigen Änderung nachgeordnet ist. Betreiber, die nicht sofort aktualisieren können, können eine eingeladene Person die Domain des Links über einen separaten Kanal prüfen lassen, bevor sie ihm folgt, und ein Praxis-Administrator kann noch nicht bestätigte Konten widerrufen und neu einladen, was das Bestätigungs-Token rotiert und ein bereits abgefangenes Token ungültig macht.
Bewertung im Detail
Host-Header.PR:NKeine Berechtigungen oder Konto erforderlich; der Endpunkt ist nicht authentifiziert und das Ziel wird über die E-Mail-Adresse der eingeladenen Person benannt.UI:RDie noch nicht bestätigte eingeladene Person muss die Bestätigungsmail öffnen und deren Link anklicken, damit das Einmal-Token den Angreifer erreicht.S:UDie Auswirkung bleibt innerhalb des Autorisierungsbereichs der Instanz.C:HDie übernommene Session liest die nur Mitarbeitern zugänglichen Daten des Mandanten, darunter den Terminkalender und das Mitarbeiterverzeichnis, auf die die Rolle zugreifen kann.I:HDie Session kann die Termindatensätze, die die Rolle verwalten darf, ändern, stornieren oder löschen.A:LDie übernommene Session kann einzelne von der Rolle verwaltete Termindatensätze entfernen, eine begrenzte Auswirkung auf die Verfügbarkeit, jedoch nicht in dem Umfang, in dem das Löschen von Staff-Key-Shares Daten dauerhaft vernichtet.Vertraulichkeit und Integrität sind High für die Mandantendaten, die die übernommene Session erreichen kann; Verfügbarkeit ist Low und spiegelt eine begrenzte Auswirkung auf die von der Rolle verwalteten Termindatensätze wider.
Referenzen
So können wir helfen
Wer wir sind
Die Sicherheitsforscher hinter diesem Sicherheitshinweis.

Dr. rer. nat. Simon Weber
Senior Pentester & MedSec-Forscher
Ich evaluiere Ihr SaMD mit derselben branchenprägenden Sicherheitsexpertise, die ich dem BAK MV für die Überarbeitung des B3S-Standards beigetragen habe.
- Promotion über Krankenhaus-Cybersicherheit
- Kritische Schwachstellen in Krankenhaussystemen gefunden
- Alumni der THB MedSec-Forschungsgruppe
- gematik Security Hero

Dipl.-Inf. Volker Schönefeld
Senior Application Security Expert
Als ehemaliger CTO und Entwickler, der zum Pentester wurde, arbeite ich mit Ihrem Team zusammen, um Schwachstellen aufzudecken und Lösungen zu finden, die zu Ihrer Architektur passen.
- 20+ Jahre als CTO, 50+ Mio. App-Downloads
- Architektur und Absicherung großer IoT-Flotten
- Certified Web Exploitation Specialist
- gematik Security Hero
Penetrationstest gesucht?
Machine Spirits ist spezialisiert auf Sicherheitsbewertungen für Medizinprodukte und Gesundheits-IT. Von MDR-Penetrationstests bis C5-Cloud-Compliance helfen wir MedTech-Unternehmen, regulatorische Anforderungen zu erfüllen.
