Verkettung von Schwachstellen: Von Self-XSS zur Account-Übernahme
Dieser Beitrag wurde aus dem Englischen übersetzt. Zum Originalbeitrag.
Einleitung
Während eines aktuellen Bug-Bounty-Engagements entdeckte ich eine interessante Angriffskette, die von einer vermeintlich harmlosen Self-XSS-Schwachstelle bis hin zu einer vollständigen Account-Übernahme (Account Takeover) eskalierte.
Dieses Szenario zeigt eindrucksvoll, wie wichtig es ist zu verstehen, dass sich scheinbar niedrig priorisierte Schwachstellen durch geschickte Kombination zu gravierenden Sicherheitsrisiken entwickeln können.
Werfen wir einen Blick auf die Details.
Erste XSS-Schwachstelle und WAF-Bypass
Ich begann meine Analyse bei einem Online-Shop (im Folgenden redacted.com), der auf PHP basierte und durch
eine Akamai Web Application Firewall (WAF) geschützt war.
Nach einiger Zeit fiel mir ein Endpoint auf, der sich von den anderen unterschied:
Normalerweise begannen die Endpoints mit
/xhr/mage/account,
dieser jedoch lautete:
/xhr_preferences/index/change/.
Dieser Endpoint diente dazu, Kundeneinstellungen zu erfassen – beispielsweise Geburtsdatum oder bevorzugte Marken – um personalisierte Produktempfehlungen zu generieren.
Ich injizierte zunächst einen einfachen HTML-Payload – mit Erfolg.
![]()
Anschließend testete ich den klassischen XSS-Payload:: "><img src=1 onerror=alert(1)>
Daraufhin erhielt ich jedoch einen 403 Forbidden-Response vom Server (AkamaiGHost).
![]()
Ich modifizierte meine Requests und testete über mehrere Stunden verschiedene XSS-Payloads, um die Akamai WAF zu umgehen – jedoch ohne Erfolg.
Nach einer Pause analysierte ich meine Logs erneut und machte eine interessante Entdeckung:
Im Feld „First Name“ konnte ich einen XSS-Payload speichern, während andere Felder weiterhin mit 403 blockiert wurden.
Was war also der Unterschied?
![]()
Der Request wurde in diesem Fall im JSON-Format gesendet und mit 200 OK beantwortet – allerdings war der Parameter selbst nicht direkt XSS-anfällig.
Daraufhin änderte ich meine Anfrage an den Endpoint /xhr_preferences/index/change/ von Query-String auf JSON.
![]()
Das Ergebnis: Ein HTTP/2 302 Found – ein deutliches Zeichen dafür, dass ich die WAF umgehen konnte, auch wenn die Daten zunächst nicht gespeichert wurden.
![]()
![]()
Nach Anpassung des Requests gelang es mir schließlich, den Payload auszuführen.
![]()
Ergebnis: Erfolgreich ausgeführte Self-XSS.
Second CSRF Bypass
Das Backend verwendete einen simplen Schutzmechanismus:
Beim Login wurde ein Cookie gesetzt – beispielsweise:
Set-Cookie: csrf=7e3f4ebc6d40b5; Path=/
Bei jeder POST-Anfrage wurde geprüft:
-
Existiert der CSRF-Token im Cookie?
-
Existiert derselbe Wert im Request-Header?
Nur wenn beide übereinstimmten, wurde die Anfrage akzeptiert (200 OK).
Andernfalls wurde die Anfrage abgelehnt.
![]()
![]()
Wie bereits festgestellt, verhielt sich der Endpoint /xhr_preferences/index/change/ anders als die übrigen.
Ich entfernte den CSRF-Header aus meinem Request – und die Anfrage wurde trotzdem akzeptiert.
Damit hatte ich alle notwendigen Voraussetzungen erfüllt.
Diese Schwachstelle ermöglichte es einem Angreifer, beliebigen JavaScript-Code im Kontext eines eingeloggten Nutzers auszuführen – und somit eine vollständige Account-Übernahme zu erreichen.
Schritte zur Reproduktion der Schwachstelle:
![]()
Angreifer
- Bearbeitet die POC.html und ersetzt attacker.com durch die eigene Domain
Opfer
-
Loggt sich in seinen Account ein
- Besucht die vom Angreifer kontrollierte Webseite
Auswirkungen und Gegenmaßnahmen
Diese Angriffskette verdeutlicht, wie mehrere Schwachstellen mit geringer Einzelwirkung in Kombination zu einem kritischen Sicherheitsvorfall führen können.
Empfohlene Maßnahmen:
-
Strikte Eingabevalidierung (Input Validation) zur Vermeidung von XS
-
Konsequente und konsistente Implementierung von CSRF-Schutzmechanismen
- Einheitliche Sicherheitsrichtlinien über alle Endpoints hinweg
Key Takeaways
- CSRF-Schutz muss für alle sicherheitsrelevanten Funktionen konsequent umgesetzt werden
- Eingaben von Nutzern sollten niemals ungeprüft verarbeitet oder ausgegeben werden
- Security Tests sollten immer Angriffsketten (Vulnerability Chaining) berücksichtigen – nicht nur isolierte Schwachstellen