HTTP/2 Request Smuggling - An Introduction

HTTP/2 Request Smuggling

An Introduction

Andrea Hauser
by Andrea Hauser
on July 07, 2022
time to read: 8 minutes

Keypoints

This is how HTTP/2 Request Smuggling works

  • Request smuggling occurs when, in a chain of servers, the servers do not agree on where the request body ends
  • HTTP/1.1 and HTTP/2 are based on different principles
  • A faulty conversion from an HTTP/2 to an HTTP/1.1 request can be exploited by attackers
  • An end-to-end HTTP/2 connection, that is, also between the front-end and the back-end, solves the problem

In the previous article, the basics of request smuggling were explained. These will be necessary for the following explanations, so those who are not yet familiar with request smuggling should first read the article on Request Smuggling – Description and Procedure for Testing.

HTTP/2 is a binary protocol. HTTP/2 messages are sent as one or more frames and each frame has an explicit length that tells the server how many bytes to read. The length of an HTTP/2 message is calculated accordingly by adding up the length of all frames. This length can not be manipulated. Now the question arises how request smuggling can still occur in HTTP/2 if the length of the frames cannot be manipulated, since this manipulation of the length was the prerequisite for request smuggling in HTTP/1.1 requests. Basically, HTTP/2 request smuggling only occurs when the front-end supports HTTP/2 but the back-end does not. Then the front-end must convert the HTTP/2 request for the back-end into an HTTP/1.1 request. This creates new possibilities for manipulation.

Since HTTP/2 is a binary protocol, abstracted and simplified representations are used here to show the concepts. The individual frames are not shown. In HTTP/2 there are so-called pseudo headers. These are defined for the rest of the article as follows and marked with a colon in front of the name

Pseudo Header Description
:method Corresponds to the request method.
:path Corresponds to the request path including possible parameters.
:authority Corresponds approximately to the host header.
:scheme Corresponds to the request scheme and is normally http or https.
:status Corresponds to the response status code and is not used in requests.

It is easiest to see these headers in use compared to the same request in HTTP/1.1 and 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

With the basics covered, HTTP/2 request smuggling vulnerabilities can now be addressed.

H2.CL Vulnerability

This vulnerability works in principle similar to the TE.CL vulnerability from the last article, but the front-end uses HTTP/2, ignores the Content-Length Header and passes it unchanged to the back-end. The back-end uses HTTP/1.1 and therefore interprets the Content-Length Header. In an example, the attack looks like this.

:method POST
:path /test
:authority example.com
content-type application/x-www-form-urlencoded
content-length 0
Injected

Since the back-end finishes processing the request earlier than what the front-end sent due to the content length of 0, the rest of the request remains in the pipeline between the front-end and the back-end. As soon as a next request arrives, the remainder of the previous request that is still in the pipeline is added before this new request. So a new request would look like this in the back-end.

InjectedGET /user-requested HTTP/1.1
Host: example.com

H2.TE Vulnerability

Similar to the vulnerability described above, the front-end uses HTTP/2, ignores the Transfer-Encoding Header and passes it unchanged to the back-end. The back-end uses HTTP/1.1 and therefore interprets the Transfer-Encoding Header. In an example, the attack looks like this.

: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

Since the back-end finishes processing the request earlier than what the front-end sent due to the transfer encoding of 0, the rest of the request remains in the pipeline between the front-end and the back-end. As soon as a next request arrives, the remainder of the previous request still in the pipeline is added before this new request. So a new request would look like this in the back-end.

POST /test HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

0
--> Request one ends here
GET /admin HTTP/1.1
Host: example.com
Foo: InjectedGET /user-requested HTTP/1.1

Request Smuggling with CRLF Injection

Since HTTP/2 and HTTP/1.1 are not interpreted on the same basis, as HTTP/2 is a binary protocol and HTTP/1.1 is string based, these differences can be exploited. In an HTTP/2 header, for example, line breaks can be used without any problems, as they are not interpreted in a special way. This means that a header interpreted as one header in the front-end can become several headers in the back-end. For example

Testheader: Test\n\rInjected

one header in the front-end, would look like this in the back-end

Testheader: Test
Injected

Due to the excellent research by James Kettel, the attacks described above can be simulated in the Web Security Academy.

Countermeasures

The easiest way to prevent this vulnerability, as already indicated at the very beginning, is to use HTTP/2 throughout. If this is not possible, care must be taken that no headers such as content length or transfer encoding and no special characters such as \r\n and : are included in the conversion to an HTTP/1.1 request.

Conclusion

When switching to HTTP/2 in the front-end server, an extensive vulnerability can be unknowingly introduced if the HTTP/2 and HTTP/1.1 speaking servers do not agree on where the limit of the request is. The effects of request smuggling can include the unauthorised reading of responses from other users, the insertion of arbitrary JavaScript into arbitrary responses from users, and the complete disruption of the normal operation of a website. The fix is comparatively easy if the back-end server can also be converted to work over HTTP/2. Otherwise, it requires careful conversion of the requests to avoid introducing vulnerabilities.

About the Author

Andrea Hauser

Andrea Hauser graduated with a Bachelor of Science FHO in information technology at the University of Applied Sciences Rapperswil. She is focusing her offensive work on web application security testing and the realization of social engineering campaigns. Her research focus is creating and analyzing deepfakes. (ORCID 0000-0002-5161-8658)

Links

Are you interested in a Penetration Test?

Our experts will get in contact with you!

×
Ways of attacking Generative AI

Ways of attacking Generative AI

Andrea Hauser

XML Injection

XML Injection

Andrea Hauser

Burp Macros

Burp Macros

Andrea Hauser

WebSocket Fuzzing

WebSocket Fuzzing

Andrea Hauser

You want more?

Further articles available here

You need support in such a project?

Our experts will get in contact with you!

You want more?

Further articles available here