Offene Redirect-Schwachstelle in Auth-Callbacks: Wie man sie behebt
Erfahren Sie, wie eine offene Redirect‑Schwachstelle in Auth‑Callbacks entsteht, wie Angreifer sie ausnutzen und wie Sie Redirects mit strikten Allowlists und sicherer URL‑Prüfung beheben.

Warum Redirects in Login-Flows zur Sicherheitslücke werden können
Ein Redirect ist eine Anweisung an den Browser: „Gehe zu dieser anderen Seite.“ In Login‑Flows sorgen Redirects dafür, dass alles nahtlos wirkt: Ihre App schickt jemanden zum Anmelden und bringt ihn danach wieder dorthin, was er ansehen wollte.
Dieser „bring mich zurück“-Schritt wird meist in einem Parameter wie returnTo, next oder redirect übergeben. Wenn Ihre App dort jede beliebige URL akzeptiert, haben Sie eine offene Redirect‑Schwachstelle.
Solche Probleme tauchen besonders in Prototypen häufig auf, weil Redirects schnell für eine glatte Demo sorgen. KI-generierter oder hastig geschriebener Code optimiert oft für „funktioniert“ und überspringt langweilige Sicherheitsregeln.
Das Risiko ist größer als „der Nutzer landet auf der falschen Seite.“ Ihre Domain wird zu einem vertrauenswürdigen Startpunkt, mit dem Angreifer Menschen auf eine bösartige Seite schicken können. Der Link wirkt legitim, weil er auf Ihrer echten Domain beginnt und oft eine vertraute Login‑Seite zeigt.
Ein realistischer Phishing‑Ablauf sieht so aus: Jemand klickt in einer E‑Mail oder einem Chat auf einen „Sign in“-Link, landet auf Ihrer echten Login‑Seite, meldet sich an und wird dann auf eine überzeugende Fake‑Seite geleitet, die ihn auffordert, sich „noch einmal anzumelden“, einen MFA‑Code einzugeben oder Zahlungsdaten zu bestätigen. Viele Nutzer merken das nicht, weil bis zum letzten Schritt alles normal aussah.
Was offene Redirects und Auth‑Callbacks bedeuten
Ein offener Redirect liegt vor, wenn Ihre App untrusted Input darüber entscheiden lässt, wohin ein Nutzer als Nächstes geschickt wird. Das klassische Beispiel ist eine URL wie https://yourapp.com/redirect?to=..., wobei to auf jede beliebige Website zeigen kann.
Ein Auth‑Callback ist die Seite, zu der Ihr Identity Provider nach dem Login zurückschickt. Nachdem sich ein Nutzer bei Google, GitHub oder einem anderen Provider angemeldet hat, sendet der Provider ihn an eine Callback‑URL in Ihrer App, damit Ihre App den Login abschließen und eine Session erstellen kann.
Probleme entstehen, wenn man die beiden Dinge kombiniert.
Ein typisches Muster:
- Ein Nutzer möchte
/billingbesuchen. - Ihre App schickt ihn zu
/login?next=/billing. - Nach dem Login liest Ihr Callback
next(oderreturnUrl,redirect,continue) aus und schickt den Nutzer dorthin.
Wenn der Callback next=https://evil.example akzeptiert, haben Sie einen offenen Redirect in dem vertrauenswürdigsten Teil Ihres Produkts eingebaut.
Die Auswirkungen beschränken sich nicht nur auf Phishing. Redirects in OAuth‑Flows können die Blast‑Radius vergrößern, wenn Teams während früher Builds sensible Werte über URLs weitergeben. Selbst wenn Sie „nur“ einen OAuth‑code hin- und herschieben, können Daten über Browser‑History, Logs, Referrer‑Header oder durch das Landen auf einer Seite, die den Nutzer austrickst, geleakt werden.
Häufige riskante Redirect‑Muster, nach denen Sie suchen sollten
Die meisten Auth‑Redirect‑Bugs beginnen gleich: Ein Team will „bring den Nutzer zurück“ und übergibt einen Redirect‑Parameter, den es dann als sicher behandelt.
Warnsignale:
- Jeder Query‑Parameter, der die Post‑Login‑Navigation steuert (
next,returnTo,redirect,url), wird direkt in einem HTTP‑Redirect oderwindow.locationverwendet. - Code, der volle URLs (
https://example.com) akzeptiert statt interner Pfade (/dashboard). - Redirect‑Ziele aus localStorage, Cookies oder Headern, die als vertraut angesehen werden.
- „Validierung“, die nur
startsWith('/')prüft. - Mehrere Decode-/Normalisierungs‑Schritte, die unklar machen, was validiert wurde und was tatsächlich benutzt wird.
Zwei Edge‑Cases stolpern viele Teams:
Protocol‑relative URLs: Werte wie //evil.com sehen wie ein Pfad aus, aber Browser behandeln sie als „aktuelles Schema verwenden und zu evil.com gehen.“ Eine einfache startsWith('/')‑Prüfung lässt das durch.
Kodierte URLs: Angreifer können denselben Trick in Kodierung verstecken. %2F%2Fevil.com wird nach dem Dekodieren zu //evil.com. Wenn Sie vor dem Dekodieren validieren oder an unterschiedlichen Stellen unterschiedlich oft dekodieren, können Sie einen String genehmigen und dann zu einem anderen weiterleiten.
Wie Angreifer offene Redirects tatsächlich ausnutzen
Angreifer mögen offene Redirects, weil sie sich das Vertrauen Ihrer Domain „ausleihen“ können. Das Opfer sieht Ihre echte Seite in der Adressleiste, meldet sich an und wird erst am Ende auf eine bösartige Seite geschickt.
Ein sehr häufiger Angriff läuft so ab:
-
Der Angreifer teilt einen Link zu Ihrer echten Domain mit einem Redirect‑Parameter, z. B.
?next=https://evil.example. -
Ihre App zeigt die echte Login‑Seite.
-
Nach der Anmeldung leitet Ihre App zum Angreifer‑Host weiter.
-
Die Angreifer‑Seite zeigt eine glaubwürdige „Session abgelaufen“‑ oder „Bestätigen Sie Ihr Konto“‑Seite und fängt Anmeldedaten oder MFA‑Codes ab.
OAuth kann das verschlimmern, wenn Ihr Callback Endpoint Codes/Tokens austauscht oder verarbeitet und dann sofort basierend auf nutzerkontrolliertem Input weiterleitet. Auch kurzlebige Daten reichen oft aus.
Ein realistisches Beispiel: Der Login‑Link, der Nutzende wegschickt
Prototypen fügen oft einen returnTo‑Parameter hinzu, damit das Login poliert wirkt.
Eine normale URL wäre:
/login?returnTo=/billing
Der Bug tritt auf, wenn returnTo als „jede URL“ statt als „sicherer Pfad in unserer App“ behandelt wird.
Jetzt funktioniert auch dies:
/login?returnTo=https://attacker.example/fake-dashboard
Nichts bricht. Der Nutzer meldet sich erfolgreich an und landet dann auf einer Seite, die wie Ihr Produkt aussieht, es aber nicht ist. Aus Sicht des Nutzers hat Ihr Login funktioniert, deshalb wirkt der nächste Bildschirm vertrauenswürdig.
Die Lektion ist einfach: Eine „bring mich zurück“-Funktion sollte nur sichere, erwartete Ziele akzeptieren. Wenn sie auf eine externe URL zeigen kann, ist das eine offene Tür.
Das sichere Modell: relative Pfade plus strikte Allowlists
Der sicherste Ansatz ist bewusst unaufregend: Behandeln Sie das Post‑Login‑Ziel als internen Pfad, nicht als volle URL.
Regel 1: Akzeptieren Sie relative Pfade, keine vollständigen URLs
Akzeptieren Sie nur Werte wie /settings oder /billing. Vermeiden Sie https://... und lehnen Sie explizit protocol‑relative Werte wie //... ab.
Eine nützliche Basisregel: Erfordern Sie ein führendes einzelnes / und lehnen Sie alles ab, was mit // beginnt.
Regel 2: Validieren Sie gegen eine strikte Allowlist
Selbst wenn Sie nur relative Pfade akzeptieren, möchten Sie vielleicht einschränken, wohin Nutzer nach dem Auth landen können. Eine Allowlist verhindert peinliche oder riskante Ziele wie /logout‑Schleifen, Routen, die sensible Aktionen auslösen, oder Seiten, die nur manche Rollen sehen sollten.
Halten Sie die Allowlist klein. Erlauben Sie eine Handvoll bekannter sicherer Routen (oder ein paar sichere Präfixe) und leiten Sie alles andere auf eine sichere Seite wie /dashboard um.
Normalisieren und parsen, bevor Sie entscheiden
Normalisieren Sie die Eingabe einmal: Trimmen Sie Whitespaces und dekodieren Sie einmal die Prozentkodierung. Validieren Sie dann den resultierenden Pfad. Vermeiden Sie doppeltes Dekodieren oder Validierungen an einer anderen Darstellung als derjenigen, zu der Sie tatsächlich weiterleiten.
Machen Sie Fehler langweilig
Ist der Wert fehlend oder ungültig, ignorieren Sie ihn und leiten Sie auf ein bekannt sicheres Ziel. Loggen Sie abgewiesene Werte, damit Sie Scans und fehlerhafte Client‑Code erkennen können.
Schritt für Schritt: Redirect‑Handling in einem Prototypen reparieren
Redirect‑Logik verteilt sich oft über Middleware, Callback‑Handler und UI‑Code. Der schnellste Weg, es sicher zu machen, ist, jedes Redirect‑Ziel als untrusted Input zu behandeln und die Validierung zu zentralisieren.
-
Inventarisieren Sie jede Redirect‑Quelle: Query‑Parameter (
next,returnTo,redirect,callback,continue), Cookies, localStorage und jede Auth‑Middleware, die „merkt“, wohin der Nutzer wollte. -
Wählen Sie Ihre Regel: Für die meisten Apps akzeptieren Sie nur relative Pfade. Falls Sie wirklich externe Redirects brauchen (selten), erlauben Sie nur eine kurze Liste exakter Origins, die Sie kontrollieren.
-
Normalisieren Sie einmal: trimmen, einmal dekodieren und Steuerzeichen ablehnen.
-
Streng validieren:
- Erfordern Sie ein führendes einzelnes
/. - Lehnen Sie
//, jedes Schema wiehttp:oderjavascript:und Backslashes (\\) ab, auch kodierte Backslashes. - Lehnen Sie Traversal wie
..und Null‑Bytes ab. - Wenn Sie volle URLs erlauben, verlangen Sie einen exakten Origin‑Match gegen Ihre Allowlist.
- Weiterleiten und loggen: Bei Fehlschlag schicken Sie den Nutzer auf eine sichere Default‑Seite und protokollieren den abgewiesenen Wert.
Häufige Fehler, die die Schwachstelle bestehen lassen
Die meisten fehlgeschlagenen Fixes sehen „validiert“ aus, behandeln Redirects aber weiterhin als einfache Strings.
Häufige Fallen:
- Allowlisting per Substring (z. B.
includes('mydomain.com')). Angreifer nutzenmydomain.com.evil.comoder verbergen vertrauenswürdigen Text im Pfad/Query. - Nur clientseitige Validierung. Clientchecks verbessern UX, aber der Server muss das finale Gate sein.
- Einen Parameter validieren, aber mit einem anderen weiterleiten wegen Framework‑Hilfen oder Parameter‑Präzedenz.
- Inkonsistente Normalisierung, Validierung vor dem Dekodieren oder mehrfaches Dekodieren.
Achten Sie außerdem auf „wir haben es früher gesetzt, also ist es vertrauenswürdig.“ Werte in localStorage, hidden fields oder Cookies kann ein Angreifer immer noch bearbeiten oder umgehen.
Schnelle Checks, die Sie vor dem Release machen können
Sie können die meisten Redirect‑Probleme mit ein paar gezielten Tests finden. Das Ziel ist einfach: Kein nutzerkontrollierter Wert darf den Browser auf eine unerwartete Domain schicken, und unbekannte Werte sollten irgendwo sicher landen.
Testen Sie den Parameter, den Ihre App nach dem Login verwendet (next, redirect, returnTo, callbackUrl). Bestätigen Sie, dass ein normaler interner Pfad funktioniert, und probieren Sie dann Eingaben, die naive Checks oft passieren lassen:
https://example.com(sollte abgelehnt werden)//evil.comund%2F%2Fevil.com(sollten abgelehnt werden)\\evil.com(manche Frameworks normalisieren das überraschend)- Eine unbekannte interne Route wie
/definitely-not-real(sollte auf eine sichere Default‑Seite fallen)
Wiederholen Sie die gleichen Tests sowohl in der Client‑Routing‑Logik als auch in den Server‑Endpoints, die Sessions abschließen oder OAuth‑Callbacks behandeln. Angreifer nutzen den schwächeren Pfad.
Nächste Schritte: zu einem sauberen, sicheren Redirect‑Setup kommen
Offene Redirect‑Bugs leben selten nur an einem Ort. In Prototypen tauchen sie überall dort auf, wo die App nach dem Login hilfreich sein will: Route Guards, Middleware, die nicht authentifizierte Nutzer weiterleitet, OAuth‑Callback‑Handler, Einladungslinks und Onboarding‑Flows.
Ein guter Endzustand ist langweilig: Jeder Redirect ist entweder ein bekannter sicherer relativer Pfad oder (wenn unbedingt nötig) eine absolute URL, die exakt mit einer kurzen Allowlist von Origins übereinstimmt, die Sie kontrollieren. Alles andere wird ignoriert und durch eine sichere Default‑Seite ersetzt.
Wenn Sie es mit einem KI‑generierten Codebase zu tun haben und eine zweite Meinung wollen: FixMyMess (fixmymess.ai) konzentriert sich darauf, solche Auth‑ und Redirect‑Probleme zu diagnostizieren und zu reparieren, zusammen mit verwandten Problemen wie offen gelegten Secrets und unsicheren Mustern, die in Demos funktionieren, aber in Produktion versagen.