HTTP request smuggling

Practice



What happens in an HTTP request smuggling attack?

Modern web applications often use chains of HTTP servers between users and the application's back-end logic. Users send requests to a front-end server (sometimes called a load balancer or reverse proxy), and this server forwards requests to one or more back-end servers. This type of architecture is becoming increasingly common, and in some cases unavoidable, in modern cloud-based applications.

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

HTTP request smuggling

In this situation, it is critically important that the front-end and back-end systems agree on the boundaries between requests. Otherwise, an attacker can send an ambiguous request that is interpreted differently by the front-end and back-end systems:

HTTP request smuggling

Here, the attacker causes part of their front-end request to be interpreted by the back-end server as the beginning of the next request. It is effectively prepended to the next request and can interfere with the way the application processes that request. This is a request smuggling attack, and it can have devastating consequences.

How do HTTP request smuggling vulnerabilities arise?

Most HTTP request smuggling vulnerabilities arise because the HTTP specification provides two different ways to specify where a request ends: the

Content-Length

header and the

Transfer-Encoding

header.

Content-Length

The header is straightforward: it specifies the length of the message body in bytes. For example:

POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

q=smuggling
Transfer-Encoding

The header can be used to indicate that the message body uses chunked encoding. This means the message body contains one or more chunks of data. Each chunk consists of the chunk size in bytes (expressed in hexadecimal), followed by a newline, followed by the chunk's contents. The message ends with a zero-size chunk. For example:

POST /search HTTP/1.1
Host: normal-website.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

b
q=smuggling
0

Note

Many security testers are unaware that chunked encoding can be used in HTTP requests, for two reasons:

  • Burp Suite automatically unpacks chunked encoding so that messages are easier to view and edit.
  • Browsers do not normally use chunked encoding in requests, and it is normally only seen in server responses.

Since the HTTP specification provides two different methods for specifying the length of HTTP messages, it is possible for a single message to use both methods at once, so that they conflict with each other. The HTTP specification attempts to prevent this problem by stating that, if both the

Content-Length

and

Transfer-Encoding

headers are present, then the

Content-Length

header must be ignored. This may be sufficient to avoid ambiguity when only one server is involved, but not when two or more servers are chained together. In this situation, problems can arise for two reasons:

  • Some servers do not support the
    Transfer-Encoding
    header in requests.
  • Some servers that do support the
    Transfer-Encoding
    header may fail to process it if the header is obfuscated in some way.

If the front-end and back-end servers behave differently with respect to a (possibly obfuscated)

Transfer-Encoding

header, then they may disagree about the boundaries between successive requests, leading to request smuggling vulnerabilities.

How to perform an HTTP request smuggling attack

Request smuggling attacks involve placing both a

Content-Length

header and a

Transfer-Encoding

header in a single HTTP request and manipulating them so that the front-end and back-end servers process the request differently. The precise way this is done depends on the behavior of the two servers:

  • 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.

CL.TE vulnerabilities

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

The front-end server processes the

Content-Length

header and determines that the request body is 13 bytes long, up to the end of

SMUGGLED

. This request is forwarded on to the back-end server.

The back-end server processes the

Transfer-Encoding

header and processes the message body using chunked encoding. It processes the first chunk, which is stated to be zero length, and so is treated as terminating the request. The following bytes,

SMUGGLED

are left unprocessed, and the back-end server will treat them as the start of the next request in the sequence.

TE.CL vulnerabilities

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

Note

To send this request using Burp Repeater, you first need to go to the Repeater menu and make sure the "Update Content-Length" option is unchecked.

You must include the trailing sequence

\r\n\r\n

after the final

0

.

The front-end server processes the

Transfer-Encoding

header and processes the message body using chunked encoding. It processes the first chunk, of length 8 bytes, up to the start of the next line,

SMUGGLED

. It processes the second chunk, which is stated to be zero length, and so is treated as terminating the request. This request is forwarded on to the back-end server.

The back-end server processes the

Content-Length

header and determines that the request body is 3 bytes long, up to the start of the next line,

8

. The following bytes, starting with

SMUGGLED

, are left unprocessed, and the back-end server will treat them as the start of the next request in the sequence.

TE.TE behavior: obfuscating the TE header

Here, both the front-end and back-end servers support the

Transfer-Encoding

header, but one of the servers can be induced not to process it by obfuscating the header in some way.

There are potentially unlimited ways to obfuscate the

Transfer-Encoding

header. For example:

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

Each of these techniques involves a subtle departure from the HTTP specification. Real code implementing the protocol specification rarely adheres to it with absolute precision, and it is typical for different implementations to tolerate different deviations from the spec. To detect a TE.TE vulnerability, you need to find some variant of the

Transfer-Encoding

header that is processed by only one of the front-end or back-end servers, while the other ignores it.

Depending on whether it is the

Transfer-Encoding

front-end or back-end server that may fail to process the disguised header, the remainder of the attack takes the same form as for the already-described CL.TE or TE.CL vulnerabilities.

How to prevent HTTP request smuggling vulnerabilities

HTTP request smuggling vulnerabilities arise in cases where a front-end server forwards multiple requests to a back-end server over the same network connection, and the protocol used for the back-end connections carries the risk that the two servers will disagree about the boundaries between requests. Below are some general ways to prevent HTTP request smuggling vulnerabilities from arising.

  • Disable reuse of back-end connections, so that each back-end request is sent over a separate network connection.
  • Use HTTP/2 for back-end connections, since this protocol prevents ambiguity regarding request boundaries.
  • Use the same web server software for the front-end and back-end servers, so that they agree on the boundaries between requests.

In some cases, vulnerabilities can be avoided by making the front-end server normalize ambiguous requests, or by making the back-end server reject ambiguous requests and close the network connection. However, these approaches are potentially more error-prone than the general mitigations listed above.

created: 2020-07-02
updated: 2026-03-10
294



Was this answer useful?
Choose a quick rating so we can improve the next answer for you.
How satisfied are you?


Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "information security - Cryptography and Cryptanalysis. Steganography. Information protection"

Terms: information security - Cryptography and Cryptanalysis. Steganography. Information protection