Ein gespeicherter HTML-Injection-Bug im Jobboard RamenHire ermöglichte es jedem, ein öffentliches Formular auszufüllen und die Benachrichtigungs-E-Mails des Teams in eine Phishing-Plattform zu verwandeln.

Wie der Bug eingeschlichen ist

RamenHire basiert auf Next.js und Supabase und ermöglicht es Startups, Stellenanzeigen zu veröffentlichen, ohne sich anmelden zu müssen. Jede Einreichung löst eine E-Mail an das interne Recruiting-Team aus. Der E-Mail-Body wird erstellt, indem rohe Formularfelder – Firmenname, Stellenbeschreibung, Kontaktname – direkt in einen HTML-String eingefügt werden. Bevor der String den Mail-Service erreicht, erfolgt weder ein Escaping noch eine Bereinigung (Sanitisation).

Da die Vorlage Benutzereingaben als sicheres HTML behandelt, kann ein böswilliger Bewerber einen gefälschten „Hier klicken zur Verifizierung“-Link einschleusen. Die Payload wird als Teil der Stellenausschreibung auf dem Server gespeichert, sodass jede nachfolgende Benachrichtigungs-E-Mail den schädlichen Code enthält. Ein Angreifer kann diesen Link direkt neben der echten Schaltfläche „Dashboard anzeigen“ platzieren und so ein Teammitglied dazu verleiten, Anmeldedaten preiszugeben oder eine Phishing-Seite zu besuchen.

Warum es wichtig war

Die E-Mails gehen an das Kern-Recruiting-Team – Personen, die ständig auf Links klicken, um Kandidaten durch den Auswahlprozess zu führen.

Die technische Lücke

Das Escaping von HTML ist kein einzelner Schritt. Zwei Kontexte müssen geschützt werden:

  • Textknoten (Text nodes) – Inhalte zwischen Tags. Das Umwandeln von < in &lt; und > in &gt; verhindert Tags, stoppt einen Angreifer jedoch nicht dabei, aus einem Attributwert auszubrechen.
  • Attributwerte – Strings innerhalb von Tags wie href="…". Das Einschleusen eines Anführungszeichens (" oder ') ermöglicht es einem Angreifer, das Attribut vorzeitig zu schließen und eigenes Markup einzufügen.

Der ursprüngliche Code verarbeitete nur Klartext, wodurch die Attribut-Injection völlig offenlag.

Das Problem beheben

Der Entwickler fügte einen kleinen escapeHtml-Helper hinzu und wandte ihn auf jeden vom Benutzer bereitgestellten Wert vor der Interpolation an, unabhängig davon, ob der Wert in einem Textknoten oder einem Attribut landet.

Verifizierungsschritte

  • Lokales Testen – Eine Reihe von Injection-Strings wurde in die Template-Funktionen eingespeist. Jeder Test zeigte nur maskierte (escaped) Zeichen, keine ausführbaren Tags.
  • Produktionstests – Nach dem Deployment des Patches wurde eine Payload über die Live-Seite eingereicht, wobei der Bot-Check von Cloudflare Turnstile erfolgreich bestanden wurde. Die resultierende E-Mail landete im Posteingang des Entwicklers; der schädliche Link und etwaige Script-Tags erschienen als unleserlicher Text und nicht als anklickbare Elemente.

Ein Hinweis zu Gmail: Der Dienst färbt eine URL möglicherweise immer noch blau ein und macht sie anklickbar, aber das ist eine clientseitige Komfortfunktion und bedeutet nicht, dass die HTML-Injection erfolgreich war. Der Fix verhindert, dass die Injection echte Schaltflächen erstellt oder Skripte ausführt.

Worauf Entwickler achten sollten

  • Vertrauen Sie niemals Daten aus öffentlichen Formularen – Selbst harmlos aussehende Formulare können gespeicherte Ausgaben erzeugen, die an anderer Stelle verwendet werden.
  • Escaping am Point of Use – Wenden Sie kontextabhängiges Escaping (Text vs. Attribut) erst unmittelbar vor dem Rendering an, nicht früher in der Pipeline.
  • Testen Sie sowohl client- als auch serverseitig – Unit-Tests erkennen offensichtliche Fehler; ein manueller End-to-End-Test über die Live-Benutzeroberfläche bestätigt, dass die Abwehrmechanismen unter realem Datenverkehr standhalten.
  • Achten Sie auf Eigenheiten von E-Mail-Clients – Einige Clients verlinken URLs automatisch, was ein falsches Gefühl von Sicherheit vermitteln kann. Überprüfen Sie, ob das zugrunde liegende HTML keine aktiven Elemente enthält.

Fazit

Ein einziges Versäumnis beim Umgang mit Benutzereingaben verwandelte routinemäßige Benachrichtigungs-E-Mails in einen Phishing-Vektor. Die Einführung einer umfassenden HTML-Escaping-Routine und die Validierung des Fixes lokal sowie in der Produktion stellten die Integrität des Posteingangs wieder her. Dieser Vorfall unterstreicht eine zeitlose Lektion für jede Web-App, die HTML aus nicht vertrauenswürdigen Daten generiert: Eine ordnungsgemäße Bereinigung ist unverzichtbar, und sie zu ignorieren, kann eine direkte Verbindung zu den Posteingängen Ihrer Nutzer eröffnen.