Sie wollen mehr?
Weitere Artikel im Archiv
So funktioniert HTTP/2 Request Smuggling
HTTP/2 ist ein binäres Protokoll. Dabei werden HTTP/2-Nachrichten in einem, bis mehreren Frames versandt und jeder Frame hat eine explizite Länge, die dem Server vorgibt, wie viele Bytes gelesen werden sollen. Die Länge einer HTTP/2-Nachricht wird dementsprechend berechnet in dem die Länge aller Frames aufsummiert wird. Diese Länge kann nicht manipuliert werden. Nun stellt sich die Frage, wie in HTTP/2 dennoch Request Smuggling entstehen kann, wenn die Länge der Frames nicht manipuliert werden kann, da diese Manipulation der Länge bei HTTP/1.1-Anfragen die Voraussetzung für das Request Smuggling war. Grundsätzlich entsteht HTTP/2 Request Smuggling nur dann, wenn das Front-End HTTP/2 spricht, das Back-End allerdings nicht. Dann muss das Front-End die HTTP/2-Anfrage für das Back-End in eine HTTP/1.1-Anfrage umwandeln. Hier entstehen dann neue Möglichkeiten für Manipulationen.
Da HTTP/2 ein binäres Protokoll ist, werden hier abstrahierte und vereinfachte Darstellungen verwendet, um die Konzepte aufzuzeigen. Die einzelnen Frames werden nicht aufgezeigt. In HTTP/2 existieren sogenannte Pseudoheader. Diese werden für den weiteren Verlauf des Artikels wie folgt definiert und mit einem Doppelpunkt vor dem Namen als solche gekennzeichnet:
Pseudoheader | Beschreibung |
---|---|
:method | Entspricht der Request Methode. |
:path | Entspricht dem Request Pfad inklusive möglichen Parametern. |
:authority | Entspricht ungefähr dem Host Header. |
:scheme | Entspricht dem Request Schema und ist im Normalfall http oder https. |
:status | Entspricht dem Response Status Code und wird in Requests nicht verwendet. |
Am einfachsten ist es diese Header im Einsatz zu sehen im Vergleich zur gleichen Anfrage in HTTP/1.1 und HTTP/2.
HTTP/1.1 Request
POST /test HTTP/1.1\r\n Host: example.com\r\n User-Agent: test\r\n Content-Length: 3\r\n \r\n x=1
HTTP/2 Request
:method POST :path /test :authority example.com :scheme https user-agent test x=1
Mit den Grundlagen abgedeckt können nun die HTTP/2 Request Smuggling-Schwachstellen angegangen werden.
Diese Schwachstelle funktioniert vom Prinzip her ähnlich wie die TE.CL Schwachstelle aus dem letzten Artikel, allerdings verwendet das Front-End HTTP/2, ignoriert den Content-Length Header und gibt ihn unverändert an das Back-End weiter. Das Back-End verwendet HTTP/1.1 und interpretiert daher den Content-Length Header. In einem Beispiel sieht der Angriff wie folgt aus.
:method POST :path /test :authority example.com content-type application/x-www-form-urlencoded content-length 0 Injected
Da das Back-End die Verarbeitung der Anfrage aufgrund der Content-Length von 0 früher beendet, als das Front-End geschickt hat, bleibt der Rest der Anfrage in der Pipeline zwischen Front-End und Back-End bestehen. Sobald eine nächste Anfrage eintrifft, wird der noch in der Pipeline vorhandene Rest der vorherigen Anfrage vor dieser neuen Anfrage hinzugefügt. Eine neue Anfrage würde im Back-End also wie folgt aussehen.
InjectedGET /user-requested HTTP/1.1 Host: example.com
Ähnlich wie bei der oben beschriebenen Schwachstelle verwendet das Front-End HTTP/2, ignoriert den Transfer-Encoding Header und gibt ihn unverändert an das Back-End weiter. Das Back-End verwendet HTTP/1.1 und interpretiert daher den Transfer-Encoding Header. In einem Beispiel sieht der Angriff wie folgt aus.
:method POST :path /test :authority example.com content-type application/x-www-form-urlencoded transfer-encoding chunked 0 GET /admin HTTP/1.1 Host: example.com Foo: Injected
Da das Back-End die Verarbeitung der Anfrage aufgrund des Transfer-Encoding von 0 früher beendet, als das Front-End geschickt hat, bleibt der Rest der Anfrage in der Pipeline zwischen Front-End und Back-End bestehen. Sobald eine nächste Anfrage eintrifft, wird der noch in der Pipeline vorhandene Rest der vorherigen Anfrage vor dieser neuen Anfrage hinzugefügt. Eine neue Anfrage würde im Back-End also wie folgt aussehen.
POST /test HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded Transfer-Encoding: chunked 0 --> Anfrage eins endet hier GET /admin HTTP/1.1 Host: example.com Foo: InjectedGET /user-requested HTTP/1.1
Da HTTP/2 und HTTP/1.1 nicht auf der gleichen Basis interpretiert werden, da HTTP/2 ein binäres Protokoll ist und HTTP/1.1 String basiert ist, können diese Unterschiede ausgenutzt werden. In einem HTTP/2 Header können zum Beispiel problemlos Zeilenumbrüche genutzt werden, da diese nicht speziell interpretiert werden. Das heisst aus einem im Front-End als ein Header interpretierten Header können im Back-End mehrere Header werden. Zum Beispiel wäre
Testheader: Test\n\rInjected
im Front-End ein Header, würde im Back-End allerdings wie folgt aussehen
Testheader: Test Injected
Danke der ausgezeichneten Forschung von James Kettel können die oben beschriebenen Angriffe in der Web Security Academy nachgespielt werden.
Diese Schwachstelle kann, wie zu Beginn bereits angedeutet, am einfachsten verhindert werden, in dem durchgehend HTTP/2 eingesetzt wird. Falls dies nicht möglich ist, muss darauf geachtet werden, dass bei der Umwandlung in einen HTTP/1.1 Request keine Header wie Content-Length oder Transfer-Encoding und keine Spezialzeichen wie \r\n und : übernommen werden.
Bei der Umstellung auf HTTP/2 im Front-End Server kann unbewusst eine weitreichende Schwachstelle eingeführt werden, wenn sich die HTTP/2 und die HTTP/1.1 sprechenden Server nicht einig sind, wo die Grenze des Requests sind. Die Auswirkungen von Request Smuggling könne das unberechtigte Lesen von Responses von anderen Benutzern, das Einfügen von beliebigem JavaScript in beliebige Responses von Benutzern, sowie das vollständige Stören eines normalen Betriebs einer Webseite sein. Die Behebung ist vergleichsweise einfach, wenn der Back-End Server ebenfalls auf HTTP/2 umgestellt werden kann. Ansonsten benötigt es eine sorgfältige Umwandlung der Requests, um keine Schwachstellen einzuführen.
Unsere Spezialisten kontaktieren Sie gern!
Andrea Hauser
Andrea Hauser
Andrea Hauser
Andrea Hauser
Unsere Spezialisten kontaktieren Sie gern!