HTTP Request Smuggling

A presentation at Internal Team Session in November 2021 in by Rohit Narayanan M

Slide 1

Slide 1

Request Smuggling Rohit Narayanan M 08-09-21

Slide 2

Slide 2

Request smuggling HTTP request smuggling is a technique for interfering with the way a web site processes sequences of HTTP requests. When you get a classic request smuggling vulnerability, it is typically because the front end and the back end disagree about whether they should use the content length or the transfer and coding header.

Slide 3

Slide 3

What is happening When the front-end server forwards HTTP requests to a back-end server, it sends several requests over the same back-end network connection, because this is much more efficient. The protocol is very simple - HTTP requests are sent one after another The receiving server parses the HTTP request headers to determine where one request ends and the next one begins:

Slide 4

Slide 4

CL & TE Headers Content-Length Transfer-Encoding header indicates the size of the message body, in bytes, sent to the recipient. header specifies the form of encoding used to safely transfer the payload body to the user. The value will be the length of the content passed chunked, compress, deflate, gzip POST /search HTTP/1.1 Host: normal-website.com Content-Length: 15 h=contentlength POST /search HTTP/1.1 Host: normal-website.com Transfer-Encoding: chunked h=transferencoding\r\n 0\r\n \r\n

Slide 5

Slide 5

How is it dangerous Attacker ● ● ● can obtain access to forbidden resources like site administration can view sensitive data or even hijack the web session of any user. can resort to other attacks like cache poisoning, XSS (cross-site scripting) without user interaction, credential hijacking, and firewall protection bypass. Attacker targets the cache server during a cache poisoning attack. The intention is to show a user a wrong page upon request. The HTTP request smuggling vulnerability can lead to an account takeover.

Slide 6

Slide 6

How to detect it The most generally effective way to detect HTTP request smuggling vulnerabilities is to send requests that will cause a time delay in the application’s responses if a vulnerability is present.

Slide 7

Slide 7

Request Smuggling ● ● ● ● CL.CL: Will send 2 Content-Length headers and the front-end will take one and the backend the other one CL.TE: The front-end server uses the Content-Length header and the back-end server uses the Transfer-Encoding header. TE.CL: The front-end server uses the Transfer-Encoding header and the back-end server uses the Content-Length header. TE.TE: The front-end and back-end servers both support the Transfer-Encoding header, but one of the servers can be induced not to process it by obfuscating the header in some way.

Slide 8

Slide 8

CL-TE Here, the front-end server uses the Content-Length header and the back-end server uses the Transfer-Encoding header. We can perform a simple HTTP request smuggling attack as follows POST / HTTP/1.1 Host: vulnerable-website.com Content-Length: 13 Transfer-Encoding: chunked 0 SMUGGLED

Slide 9

Slide 9

CL-TE POST / HTTP/1.1 Host: vulnerable-website.com Transfer-Encoding: chunked Content-Length: 4 1 A X Since the front-end server uses the Content-Length header, it will forward only part of this request, omitting the X. The back-end server uses the Transfer-Encoding header, processes the first chunk, and then waits for the next chunk to arrive. This will cause an observable time delay.

Slide 10

Slide 10

TE-CL Here, the front-end server uses the Transfer-Encoding header and the back-end server uses the Content-Length header. We can perform a simple HTTP request smuggling attack as follows: POST / HTTP/1.1 Host: vulnerable-website.com Content-Length: 3 Transfer-Encoding: chunked 8 SMUGGLED 0

Slide 11

Slide 11

TE-CL POST / HTTP/1.1 Host: vulnerable-website.com Transfer-Encoding: chunked Content-Length: 6 0 X Since the front-end server uses the Transfer-Encoding header, it will forward only part of this request, omitting the X. The back-end server uses the Content-Length header, expects more content in the message body, and waits for the remaining content to arrive. This will cause an observable time delay.

Slide 12

Slide 12

TE-TE Can be done by obfuscating the Transfer-Encoding header ● ● ● ● ● ● ● ● ● Transfer-Encoding: xchunked Transfer-Encoding : chunked Transfer-Encoding: chunked Transfer-Encoding: x Transfer-Encoding:[tab]chunked [space]Transfer-Encoding: chunked X: X[\n]Transfer-Encoding: chunked Transfer-Encoding : chunked

Slide 13

Slide 13

DEMO ● ● CL.TE TE.CL

Slide 14

Slide 14

Real world impacts Gunicorn accepts a plus sign or a minus sign in front of the value in the Content-Length header. Also a bug was discovered which causes Gunicorn to send the response before reading the body of the corresponding request. This only occurs if the request handler invoked by Gunicorn never reads any part of the body. Combining both We can send the request and gunicorn Will see this

Slide 15

Slide 15

Chunk Extension There is a proxy which parses chunk extensions incorrectly. It reads the chunk size and then reads any character until it encounters a \n. It doesn’t verify whether there was a CR before the LF. This could be combined with many of the servers tested since most servers allow any characters as part of the extension (particularly LF) but read the line until they reach CRLF. So we arrive at the following attack (all lines are terminated by CRLF): Here the proxy will see 2 chunks While the server will only see one chunk and another request after it.

Slide 16

Slide 16

HTTP/2 Here is an HTTP/1.1 request and its Equivalent request in HTTP/2

Slide 17

Slide 17

HTTP/2 Pseudo-Headers In HTTP/1, the first line of the request contains the request method and path. HTTP/2 replaces the request line with a series of pseudo-headers. The five pseudo-headers are easy to recognize as they’re represented using a colon at the start of the name: :method - The request method :path - The request path. Note that this includes the query string :authority - The Host header, roughly :scheme - The request scheme, typically ‘http’ or ‘https’ :status - The response status code - not used in requests

Slide 18

Slide 18

HTTP/2 Binary Protocol HTTP/1 is a text-based protocol, so requests are parsed using string operations. For example, a server needs to look for a colon in order to know when a header name ends. The potential for ambiguity in this approach is what makes desync attacks possible. HTTP/2 is a binary protocol like TCP, so parsing is based on predefined offsets and much less prone to ambiguity. This paper represents HTTP/2 requests using a human-readable abstraction rather than the actual bytes. For example, on the wire, pseudo-header names are actually mapped to a single byte - they don’t really contain a colon.

Slide 19

Slide 19

HTTP/2 Message Length In HTTP/1, the length of each message body is indicated via the Content-Length or Transfer-Encoding header. In HTTP/2, those headers are redundant because each message body is composed of data frames which have a built-in length field. This means there’s little room for ambiguity about the length of a message, and might leave you wondering how desync attacks using HTTP/2 are possible. The answer is HTTP/2 downgrading.

Slide 20

Slide 20

HTTP/2 Desync Attacks HTTP/2 downgrading is when a front-end server speaks HTTP/2 with clients, but rewrites requests into HTTP/1.1 before forwarding them on to the back-end server. This protocol translation enables a range of attacks, including HTTP request smuggling:

Slide 21

Slide 21

H2.CL vulnerabilities HTTP/2 requests don’t have to specify their length explicitly in a header. During downgrading, front-end servers often add a Content-Length header, its value using HTTP/2’s built-in length mechanism. some front-end servers will simply reuse the value of content-length passed

Slide 22

Slide 22

DEMO ● H2.CL

Slide 23

Slide 23

H2.TE vulnerabilities Chunked transfer encoding is incompatible with HTTP/2 and the spec recommends that any transfer-encoding: chunked header you try to inject should be stripped or the request blocked entirely. If the front-end server fails to do this, and subsequently downgrades the request for an HTTP/1 back-end that does support chunked encoding, this can also enable request smuggling attacks.

Slide 24

Slide 24

Response Queue Poisoning Front-end server to start mapping responses from the back-end to the wrong requests Attacker can capture other users’ responses by issuing arbitrary follow-up requests

Slide 25

Slide 25

Response Queue Poisoning The front-end correctly maps the first response to the initial request There is no further requests When the front-end receives another request, it forwards this to the back-end as normal. However, when issuing the response, it will send the first one in the queue, that is, the leftover response to the smuggled request.

Slide 26

Slide 26

Request smuggling via CRLF injection ● ● ● ● In HTTP/1, you can sometimes exploit discrepancies between how servers handle standalone newline (\n) This discrepancy doesn’t exist with the handling of a full CRLF (\r\n) sequence because all HTTP/1 servers agree that this terminates the header. HTTP/2 messages are binary. So \r\n no longer has any special significance So it can be included inside the value itself without causing the header to be split

Slide 27

Slide 27

HTTP request tunnelling some servers only allow requests originating from the same IP address or the same client to reuse the connection. Others won’t reuse the connection at all you can send a single request that will elicit two responses from the back-end. This enables you to hide a request and its response from the front-end altogether.

Slide 28

Slide 28

Leaking internal headers You can potentially trick the front-end into appending the internal headers inside what will become a body parameter on the back-end. Let’s say we send a request that looks something like this: he front-end sees everything we’ve injected as part of a header, so adds any new headers after the trailing comment= string.

Slide 29

Slide 29

How to prevent It ● ● Use HTTP/2 end to end and disable HTTP downgrading if possible. HTTP/2 uses a robust mechanism for determining the length of requests and, when used end to end, is inherently protected against request smuggling. If you can’t avoid HTTP downgrading, make sure you validate the rewritten request against the HTTP/1.1 specification. For example, reject requests that contain newlines in the headers, colons in header names, and spaces in the request method. Make the front-end server normalize ambiguous requests and make the back-end server reject any that are still ambiguous, closing the TCP connection in the process.

Slide 30

Slide 30

References ● ● ● ● ● ● ● https://portswigger.net/web-security/request-smuggling https://portswigger.net/web-security/request-smuggling/advanced https://snyk.io/blog/demystifying-http-request-smuggling/ https://blog.zeddyu.info/2019/12/08/HTTP-Smuggling-en/ https://www.cgisecurity.com/lib/http-request-smuggling.pdf https://grenfeldt.dev/2021/10/08/gunicorn-20.1.0-public-disclosure-of-re quest-smuggling https://www.youtube.com/watch?v=rHxVVeM9R-M