Wie Angreifer mit HTTP Request Smuggling die Sitzung eines Benutzers übernehmen können – Exploit-Walkthrough
Während eines Einsatzes bei einem Kunden stieß ich kürzlich auf eine Instanz einer eher seltenen Schwachstelle namens HTTP-Request Smuggling. Im Laufe mehrerer zermürbender Tage zur Ausarbeitung eines Exploits war ich schließlich in der Lage, diese Schwachstelle zu missbrauchen, um eine Desynchronisierung der Response Queue auszulösen, die es mir ermöglichte, die Anfragen anderer Benutzer zu erfassen, was zu einem Session-Hijacking führte.
Im Folgenden erfahren Sie, was ich gelernt habe, wie ich vorgegangen bin und worauf Sie achten sollten, um Ihr Unternehmen vor dieser Sicherheitslücke zu schützen.
Was ist HTTP Request Smuggling?
HTTP-Request-Smuggling ist hier bei Portswigger sehr gut dokumentiert worden, daher werde ich kurz die Grundlagen meines speziellen Falles behandeln. Kurz gesagt, HTTP-Request-Smuggling-Schwachstellen entstehen durch eine Unstimmigkeit zwischen einem Front-End- und einem Back-End-Server über die Größe des Message-Bodys. Diese Unstimmigkeit kann dazu missbraucht werden, die Verarbeitung von Benutzeranfragen durch eine Webanwendung zu stören.
Dies wird meist dadurch ausgelöst, dass beide Methoden zur Angabe der Nachrichtenlänge (die Header „Content-Length“ und „Transfer-Encoding“) zu einer einzigen Anfrage hinzugefügt werden. Wenn sich die Front-End- und Back-End-Server nicht einig sind, welche Spezifikation der Nachrichtenlänge zu verwenden ist, kommt es zu einer Desynchronisierung, und die Anwendung ist wahrscheinlich einer Request Smuggling-Schwachstelle ausgeliefert.
Erkennung von TE:CL Request Smuggling
Das Aufspüren von Request-Smuggling-Schwachstellen kann schwierig sein, da die Header in der Spezifikation von HTTP definiert sind. Portswigger hat jedoch ein hervorragendes Tool entwickelt, um diesen Prozess zu beschleunigen. Während wir unsere übliche Discovery-Phase gegen die fragliche Anwendung abschlossen, erhielten wir eine Meldung von Portswiggers Tool, die uns mitteilte, dass es möglicherweise eine Diskrepanz in der Art und Weise gibt, wie die Anwendung die Header „Content-Length“ und „Transfer-Encoding“ behandelt.
In unserem Fall lag die festgestellte Diskrepanz in der Tatsache, dass das Front-End den „Transfer-Encoding“-Header und das Back-End den „Content-Length“-Header verwenden würde, daher „TE:CL Request Smuggling“. Um die Aufforderung des Tools zu bestätigen, führten wir eine Anfrage durch, die in etwa so aussah:
In Abbildung 1 sehen Sie, wie das Frontend unsere Anfrage empfängt und den „Transfer-Encoding“-Header (gelb hervorgehoben) als Standard verwendet. Das Front-End liest also alles bis auf das „X“-Zeichen ein und leitet die Anfrage an den Back-End-Server weiter. Der Back-End-Server, der den „Content-Length“-Header verwendet, versucht, 6 Bytes an Daten einzulesen, erhält aber nur 5, weil das Front-End das letzte „X“-Zeichen, wie im „Transfer-Encoding“-Header angegeben, ignoriert hat.
Dies führt zu einer spürbaren Verzögerung und schließlich zu einer Zeitüberschreitung, da der Back-End-Server auf das letzte Byte der Daten wartet. Diese Verzögerung bestätigt das Vorhandensein einer Desynchronisation und ermöglicht es uns, uns auf die Bewertung verschiedener Techniken zum Request Smuggling zu konzentrieren.
Nachweis von TE:CL-Schwachstellen durch Request Smuggling
Nachdem wir manuell überprüft haben, dass eine Desynchronisierung vorliegt, können wir versuchen, eine Anfrage an den Back-End-Server zu „schmuggeln“, um zu beweisen, dass die Schwachstelle für das Request Smuggling genutzt werden kann. Zu diesem Zweck müssen wir zwei Anfragen senden. Bei der ersten handelt es sich um den Versuch eines Angreifers, ein Anfragepräfix in den Körper einer regulären Anfrage zu schmuggeln, und bei der zweiten um eine reguläre Anfrage, die unser Opfer simuliert.
In Abbildung 2 unten sehen Sie die erste Anfrage dieses Paares (die Anfrage des Angreifers). Auch hier verwendet der Front-End-Server den „Transfer-Encoding“-Header, der – und das ist wichtig – korrekt angepasst ist und das gesamte geschmuggelte Anfragepräfix im Body an den Back-End-Server weiterleitet.
Das Backend liest diese Anfrage wiederum mit Hilfe des „Content-Length“-Headers ein, der nach den Zeichen „74“ aufhört. Der Angreifer erhält nun einfach eine Antwort auf die ursprüngliche POST-Anfrage in Richtung „/“. Das eingeschmuggelte Präfix „GET /404 HTTP/1.1“ verbleibt jedoch in der Anfragewarteschlange, da das Backend dies als Beginn einer neuen Anfrage betrachtet. Diese „neue“ Anfrage hat eine „Content-Length“ von 15 (länger als der angegebene Anfragebody von „x=y 0“), was das Back-End veranlasst, auf die restlichen Bytes zu warten.
Wenn der Angreifer den richtigen Zeitpunkt abpasst und das Opfer zufällig kurz nach der geschmuggelten Anfrage eine Anfrage sendet, wird seine Anfrage vom Back-End als die verbleibenden Bytes der geschmuggelten Anfrage eingelesen. Je nachdem, was sie geschmuggelt haben, erhält der Angreifer so die Kontrolle über die Benutzerdaten.
Abbildung 3 – Schmuggel von Anfragen aus der Sicht des Opfers
In der obigen Abbildung 3 sehen Sie den Ablauf der zweiten Anfrage in der Kette (die Anfrage des Opfer-Nutzers). Der gesamte Fluss findet statt, während der Back-End-Server auf den Rest des „GET /404 HTTP/1.1“-Anfragekörpers wartet. Da das Back-End auf die verbleibenden Bytes wartet, wird die Anfrage des Opfers einfach an unser geschmuggeltes Präfix angehängt, was dazu führt, dass das Opfer seine Profilseite anfordert und stattdessen eine 404-Seite erhält. Dieser Vorgang bestätigt, dass wir die Anfrage des Opfers durch das Schmuggeln von Anfrage-Präfixen manipulieren können.
Ausarbeitung eines Exploits
Einem Benutzer eine zufällige 404-Seite zu liefern, ist nicht das gewünschte Ergebnis, wenn wir unseren Kunden die Risiken einer Sicherheitslücke aufzeigen wollen. Wir wollen etwas bauen, das das volle Potenzial von HTTP-Request-Smuggling-Schwachstellen realistisch darstellt.
Ähnlich wie bei der Erklärung im vorherigen Abschnitt konnten wir ein Präfix für eine offene Weiterleitungsschwachstelle schmuggeln, da man beim Schmuggeln von Anfragen die vollständige Kontrolle über den Host-Header hat:
In Abbildung 4 sehen Sie die geschmuggelte Anfrage, die zur Durchführung der 302-Umleitung erstellt wurde. Wenn diese Anfrage eingeschleust wird, führt jede Opferanfrage, die an die eingeschleuste Anfrage angehängt wird, zu einer Umleitung zu Outpost24.com. Dies wäre theoretisch für das ungeübte Auge fast unbemerkbar, da die Umleitung erfolgen kann, wenn das Opfer auf einen beliebigen Link auf den Seiten der legitimen Website klickt. Auf diese Weise könnte ein Angreifer Benutzer zu bösartigen Inhalten umleiten, z. B. zu einer gefälschten Anmeldeseite, um einen fortgeschrittenen Phishing-Angriff durchzuführen. Dieser Angriff ist zwar sehr wirkungsvoll, setzt aber eine starke Interaktion des Benutzers mit der Seite voraus und bietet einem gut geschulten Benutzer die Möglichkeit, zu erkennen, dass er auf eine neue Domain umgeleitet wurde.
Nach vielen Nachforschungen und verzweifeltem Googeln fand ich im Internet eine kurze Erklärung für HTTP/1 Response Queue Poisoning, eine Technik, von der ich zunächst annahm, dass sie nur für HTTP/2 gilt. Dieser Exploit bot die Möglichkeit, die Antwort-Warteschlange der Anwendung zu manipulieren, so dass wir eine für einen anderen Benutzer bestimmte Antwort erhielten. Wenn wir diese Technik mit unserem bestehenden Schmuggeln von teilweisen Anfrage-Präfixen kombinieren, könnten wir einen kleinen, reflektierten Parameter auf der Anmeldeseite der Anwendung missbrauchen, um die Anfragen der Opfer in einer HTTP-Antwort zu speichern. Diese Antwort könnte dann an uns (den Angreifer) und nicht an das Opfer übermittelt werden.
Desynchronisierung der Response-Queue
Der erste Schritt des Exploits besteht darin, die Antwort-Warteschlange zu manipulieren, indem eine zusätzliche Anfrage eingeschleust wird. Dadurch wird eine Desynchronisation in der Antwort-Warteschlange ausgelöst, so dass die Benutzer Antworten erhalten, die anderen Benutzern gehören. Das hört sich ziemlich kompliziert an, ist aber in Wirklichkeit eine einfache Erweiterung der Schwachstellen beim Request Smuggling.
Bisher haben wir in den von uns betrachteten Beispielen immer versucht, ein Anfrage-„Präfix“ zu schmuggeln. Mit anderen Worten, nur den Anfang einer Anfrage, so dass die nächste Anfrage in der Warteschlange an unser geschmuggeltes Präfix angehängt wird. In diesen Fällen sind sich das Front-End und das Back-End nie uneinig darüber, welcher Anforderung eine Antwort zugeordnet werden soll. Wenn wir jedoch eine gesamte Anfrage an den Back-End-Server schmuggeln, muss sich das Front-End plötzlich mit einer zusätzlichen Antwort auseinandersetzen, die es nicht erwartet hat. In den Abbildungen 5, 6, 7 und 8 finden Sie einen Überblick über diesen Prozess.
Abbildung 8 – GIF des gesamten Ablaufs
Wie Sie sehen, kann ein Angreifer durch das Einschleusen einer zusätzlichen Anfrage in die Warteschlange die Antwort eines Opfers anstelle seiner eigenen Antwort erhalten. Dieser Angriff ist für sich genommen schon ziemlich wirkungsvoll, aber für die Anwendung, die ich getestet habe, wollte ich die Anfrage des Opfers abfangen, da sie immer das API-Zugangs-Token des Opfers enthalten würde.
Abfangen von Nutzeranfragen
Um die Anfragen anderer Benutzer mithilfe von Response Queue Poisoning zu erhalten, brauchte ich ein Gadget, mit dem ich die Anfrage eines Opfers auf einer Seite widerspiegeln konnte. Dies konnte auf der Anmeldeseite der Anwendung durch traditionelles Request Smuggling erreicht werden. Der schwierige Teil bestand darin, diesen Prozess mit Response Queue Poisoning zu verknüpfen, so dass ich (der Angreifer) die Antwort erhalten würde, die die Seite enthält, in die die Anfrage des Benutzers geschrieben wurde.
Betrachten wir zunächst, wie wir die Anfrage des Opfers auf die Anmeldeseite übertragen können. Dies war möglich, da die Login-Anfrage einen „VersionInfo“-Parameter enthielt, der beliebige Eingaben auf der Seite widerspiegeln würde (Abbildung 9). Alles, was wir tun mussten, war, diese Anfrage so zu schmuggeln, dass die Anfrage des Benutzers als der Inhalt des „VersionInfo“-Parameters endet.
Abbildung 9 – Der Inhalt von „VersionInfo“ wird auf der Anmeldeseite reflektiert.
In Abbildung 10 können Sie sehen, wie ich das Reflection-Gadget geschmuggelt habe. Beachten Sie, dass die Anfrage des Opfers aufgrund des sehr großen „Content-Length“-Headers an diese Anfrage angehängt wird. Abbildung 11 zeigt eine Demonstration der Spiegelung unserer eigenen Anfrage zurück auf die Anmeldeseite mit dieser Technik.
Abbildung 11 – Reflection Gadget, das unsere eigene Schmuggelanfrage erfasst und auf der Anmeldeseite wiedergibt.
Nachdem ich nun gezeigt habe, dass eine Anfrage auf die Anmeldeseite gespiegelt werden kann, ist es an der Zeit, den Angriff mit Response Queue Poisoning zu verketten, so dass ich (der Angreifer) die Antwort auf das Reflection Gadget erhalte und am Ende die Anfrage eines anderen Benutzers einfängt. Um dies zu erreichen, habe ich etwa die folgende Anfrage gesendet:
Abbildung 12 – Darstellung des endgültigen Angriffs-Payloads.
In Abbildung 12 sehen Sie eine Darstellung des endgültigen Payloads, der in diesem Angriff verwendet wurde. Die Anfrage verursacht gleichzeitig eine Desynchronisierung der Antwortwarteschlange und schmuggelt das Präfix für unsere Reflection-Gadget-Anfrage, was dazu führt, dass die Anfrage des Opfers in der Antwort auf den Endpunkt „/ReflectionGadget“ gespeichert wird, die dank der Desynchronisierung der Antwortwarteschlange an den Angreifer zurückgesendet wird.
Um dies aufzuschlüsseln, habe ich jede einzelne Anfrage hervorgehoben. In Schwarz sehen Sie den normalen Request Smuggling-Angriff, bei dem die Header „Transfer-Encoding“ und „Content-Length“ gesetzt sind, um beide Requests an den Back-End-Server zu schmuggeln.
In Grün sehen Sie die Anfrage, die die Desynchronisierung der Antwort-Warteschlange verursacht. Beachten Sie, dass diese Anforderung einen korrekt angepassten „Content-Length“-Header hat. Diese Anfrage braucht auch absichtlich lange, um verarbeitet zu werden, um die Wahrscheinlichkeit zu erhöhen, dass die Anfrage eines Opfers an der richtigen Stelle in der Warteschlange landet (direkt nach unserer geschmuggelten „ReflectionGadget“-Anfrage).
In Rot die „ReflectionGadget“-Anfrage, die ein Anfrage-Präfix ist (weil ihre „Content-Length“ viel größer ist als die Größe des eigentlichen Anfragekörpers), so dass die Anfrage unseres Opfers an sie angehängt werden kann.
Abbildung 13 – Endgültiger Ablauf der Anfrage des Exploits
In Abbildung 13 sehen Sie den endgültigen Ablauf des Exploits, der dazu führt, dass der Angreifer die Anfrage des Opfers erhält. Durch das wiederholte Senden der ersten Anfrage des Angreifers, während es einen aktiven Opferbenutzer gibt, wird die Anwendung uns schließlich eine Antwort mit der Anfrage des Opferbenutzers liefern, was uns ermöglicht, sein Zugriffstoken zu stehlen und somit die Sitzung des Benutzers zu übernehmen.
Abbildung 14 unten zeigt den endgültigen Exploit, der zum Abfangen von Anfragen anderer Benutzer verwendet wird. Zunächst fangen wir unsere eigene Anfrage ab, was ein üblicher Nebeneffekt des wiederholten Sendens unseres Exploits an die Anwendung ist. Die zweite Antwort, die wir überprüfen, enthält jedoch die Anfrage eines Opferbenutzers, einschließlich seines Zugriffstokens.
Abbildung 14 – Live-Erfassung von Benutzeranfragen.
Schützen Sie Ihr Unternehmen vor Sicherheitslücken und Exploits
Um HTTP Request Smuggling-Schwachstellen vorzubeugen, empfehlen wir die folgenden High-Level-Maßnahmen (von Portswigger), sowie regelmäßige und manuelle Tests, denn Sie werden diese Art von Schwachstellen nur mit gründlichen manuellen Pen-Tests finden. Sicherheitsexperten benötigen Zeit, um die Schwachstellen zu entdecken und zu einem Proof-of-Concept auszuarbeiten (z. B. das Erfassen einer Benutzeranfrage).
Pen-Tests sind ein wichtiges Mittel, um sicherzustellen, dass sich Schwachstellen in einer Anwendung nicht zu ernsthaften Bedrohungen entwickeln – aber es kann eine schwierige und zeitaufwändige Aufgabe sein, sie firmenintern durchzuführen. Die in diesem Artikel gezeigte Schwachstelle und der Exploit sind ein fantastisches Beispiel dafür, wie weit unsere Tester gehen, um eine Schwachstelle bis an ihre Grenzen zu treiben. Es ist auch erwähnenswert, dass es Tage dauern kann, sich auf Ergebnisse wie diese zu konzentrieren, um einen praktikablen Proof-of-Concept zu erstellen, der in unseren Ergebnissen prägnant dargestellt werden kann.
Outpost24 bietet mit SWAT eine umfassende Pen-Testing-as-a-Service (PTaaS)-Lösung an, die eine kontinuierliche Überwachung von Webanwendungen im Internet über ein SaaS-Modell ermöglicht. Die Lösung kann vollständig an Ihre Bedürfnisse angepasst werden, wodurch unnötige Belastungen oder Risiken für sensible Umgebungen minimiert werden. Die meisten Sicherheitslücken werden von unserem hauseigenen Testteam gefunden und von einem erfahrenen Pen-Tester evaluiert.
SWAT kombiniert die Gründlichkeit und Präzision manueller Penetrationstests mit Schwachstellen-Scans, um Webanwendungen im großen Rahmen zu sichern. Über das Portal können Sie auch direkt mit unseren Sicherheitsexperten in Kontakt treten, um Hinweise zur Validierung und Behebung von Schwachstellen zu erhalten. Erfahren Sie mehr über SWAT und fordern Sie eine Live-Demo an.
Outpost24 Ghost Labs
Ghost Labs ist die spezialisierte Sicherheitsabteilung von Outpost24, die fortschrittliche Sicherheitsdienstleistungen wie erweiterte Netzwerk-Penetrationstests, Web-Anwendungstests, Red Teaming-Assessments und komplexe Angriffe anbietet. Darüber hinaus leistet das Ghost Labs-Team einen aktiven Beitrag zur Community mit Schwachstellenforschung und koordinierten Programmen zur verantwortungsvollen Offenlegung von neuen Ergebnissen.
Ghost Labs führt Hunderte von erfolgreichen Penetrationstests für seine Kunden durch, die von globalen Unternehmen bis hin zu KMU reichen. Unser Team besteht aus hochqualifizierten ethischen Hackern, die ein breites Spektrum an fortschrittlichen Testdienstleistungen abdecken, um Unternehmen dabei zu helfen, mit den sich entwickelnden Bedrohungen und neuen Technologien Schritt zu halten.