Prompt Injection
Andrea Hauser
So funktioniert browser-gestütztes Request Smuggling
Dier Artikel basiert stark auf der Recherche von James Kettel, die an der Defcon 30 präsentiert wurde. Basierend darauf wurden in der Portswigger Web Academy Labs zum Thema Client-Side Desync aufgebaut, mit denen diese Angriffe in der Praxis ausprobiert werden können.
Die bisherigen Request Smuggling Angriffe haben alle darauf basiert unterschiedliche Interpretationen mittels Content-Length und Transfer-Encoding Headern zwischen mehreren Servern in einer Kette zu erreichen. Beim CL.0 Angriff geht es darum, dass gewisse Server immer davon ausgehen, dass der Request keinen Body mitschickt und die dementsprechend eine Content-Length von 0 annehmen. Wenn also der Back-End Server immer eine Content-Length von 0 annimmt, der Front-End Server allerdings die mitgegebene Content-Length übernimmt, kann es so zu Diskrepanzen kommen. Das Testen, ob eine CL.0 Schwachstelle vorhanden ist, ist sehr einfach.
POST /vulnerable-endpoint HTTP/1.1 Host: example.com Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 33 --> gültige Content-Length GET /shouldBe404 HTTP/1.1 Foo: x
Es handelt sich beim oben gezeigten um einen kompletten Request mit einer gültigen Content-Length, der im Body einen zweiten nicht vollständigen Request beinhaltet. Wenn in der Antwort auf einen zweiten gültigen Request kurz nach diesem ersten abgesetzten Request eine 404-Antwort erhalten wird, kann davon ausgegangen werden, dass eine CL.0 Request Smuggling Schwachstelle vorhanden ist. Mit der CL.0 Schwachstelle können die gleichen Schwachstellen ausgenutzt werden, wie sie in den letzten Labs aufgezeigt wurden. Am anfälligsten für CL.0 Schwachstellen sind Endpunkte, die keinen POST-Request erwarten, zum Beispiel statische Dateien oder Redirects.
Bis anhin wurden Request Smuggling Angriffe als ein serverseitiges Problem betrachtet, da es sich um Missverständnisse zwischen mehreren Servern in einer Kette handelt. Diese können nicht aus dem Browser ausgelöst werden, da sie bewusst manipulierte beziehungsweise ungültige Requests verwenden. Mit der CL.0 Schwachstelle gibt es nun allerdings die Möglichkeit Angriffe auch aus dem Browser auszulösen, da es sich bei der CL.0 Schwachstelle um Requests handelt, die nicht ungültig sind, also von einem Browser ausgestellt werden können. Eine Client-Side Desync Angriff ist das Ausnützen einer Schwachstelle, bei dem die Verbindung zwischen dem Browser und einem Server desynchronisiert wird. Dementsprechend eröffnen sich auch neue Angriffswege, da nun nicht mehr nur eine Kette von Servern angegriffen werden können, sondern auch alleinstehende beziehungsweise einzelne Server.
Abstrahiert gesagt besteht ein Client-Side Desync Angriff aus den folgenden Schritten:
In Code sieht das ganze wie folgt aus:
<html> <script> fetch('https://example.com/vulnerable-endpoint', { method: 'POST', body: 'GET /thisShouldBe404 HTTP/1.1\\r\\nFoo: x', credentials: 'include' // damit der "with-cookies" Connection Pool für den Verbindungsaufbau verwendet wird }).then(() => { location = 'https://example.com/' // hier wird die desynchronisierte Verbindung genutzt }) </script> </html>
Nach Besuch dieser Webseite in einem Browser sollten im Netzwerk-Tab zwei Requests ersichtlich sein. Falls der Angriff erfolgreich war, wird der zweite Aufruf, der normalerweise mit 200 OK beantwortet wird, mit 400 Bad Request beantwortet. Dieses Beispiel kann für die Verifikation einer Client-Side Desync Schwachstelle genutzt werden. Für einen tatsächlichen Angriff würde der Angreifer im Body einen Request definieren, der den Inhalt des zweiten, desynchronisierten Request des Opfers im Account des Angreifers abspeichert. Damit würde der Angreifer an die Cookies des Opfers kommen und kann die Session des Opfers übernehmen.
Das oben gezeigte Beispiel funktioniert allerdings nicht in allen Fällen, denn wenn ein serverseitiger Redirect ausgelöst wird, wird der Code-Bereich der im .then()
definiert ist, nicht ausgeführt, sondern der Browser folgt dem Redirect. Damit der Redirect verhindert werden kann und der Client-Side Desync Angriff funktioniert, kann folgender Code verwendet werden.
<html> <script> fetch('https://example.com/redirect-endpoint', { method: 'POST', body: 'GET /thisShouldBe404 HTTP/1.1\\r\\nFoo: x', mode: 'cors', // wird bewusst gesetzt, damit ein Fehler geworfen wird und der Redirect abgebrochen wird credentials: 'include' }).catch(() => { // hier wird der CORS-Fehler aufgefangen und die desynchronisierte Verbindung genutzt fetch('https://example.com/', { mode: 'no-cors', credentials: 'include' }) }) </html> </script>
Nach Besuch dieser Webseite in einem Browser sollten wie im vorherigen Beispiel im Netzwerk-Tab zwei Requests ersichtlich sein. Falls der Angriff erfolgreich war, wird der zweite Aufruf, der normalerweise mit 200 OK beantwortet wird, mit 400 Bad Request beantwortet. Eine umfängliche Schritt für Schritt Anleitung wie auf Client-Side Schwachstellen getestet werden kann ist in der Portswigger Web Academy ersichtlich.
Mit Client-Side Desync Angriffen erweitert sich das Feld für Request Smuggling erneut und es kann zu weiteren spannenden Angriffsszenarien führen, da nun auch der Angriff auf einzelne Server möglich wird. Da die Research von James Kettel durchgeführt wurde, der bei Portswigger angestellt ist, bedeutet dies, dass das Tooling zum Auffinden dieser neuen Schwachstellen-Typen bereits ausgezeichnet ist, da in aktuellen Versionen von Burp die Identifikation dieser Schwachstellen bereits eingebaut ist. Für eine erweiterte Abdeckung wird die HTTP Request Smuggler Erweiterung empfohlen.
Unsere Spezialisten kontaktieren Sie gern!
Andrea Hauser
Andrea Hauser
Andrea Hauser
Andrea Hauser
Unsere Spezialisten kontaktieren Sie gern!