# HTTP request smuggling

![http-request-smuggling](https://2753068357-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7KQ4F0M3A1jSCGxOdZRW%2Fuploads%2Fgit-blob-457891b76f8a16f0f577c3abe9dccd2326ab53e0%2Fhttp-request-smuggling.svg?alt=media)

{% hint style="success" %}
**Лабораторные работы**

Если вы уже знакомы с контрабандой HTTP-запросов и просто хотите попрактиковаться на серии намеренно уязвимых сайтов, ознакомьтесь со ссылкой ниже для обзора всех лабораторных работ по этой теме.

* [Посмотреть все лабораторные работы по контрабанде HTTP-запросов](https://portswigger.net/web-security/all-labs#http-request-smuggling)
  {% endhint %}

## Что такое HTTP request smuggling?

Контрабанда HTTP-запросов — это техника вмешательства в то, как веб-сайт обрабатывает последовательности HTTP-запросов, получаемые от одного или нескольких пользователей. Уязвимости контрабанды часто носят критический характер, позволяя злоумышленнику обходить средства защиты, получать несанкционированный доступ к конфиденциальным данным и напрямую компрометировать других пользователей приложения.

Контрабанда запросов в основном связана с запросами HTTP/1. Однако сайты, поддерживающие HTTP/2, могут также быть уязвимы в зависимости от их архитектуры бэкэнда.

{% hint style="info" %}
**Исследования PortSwigger**

Впервые контрабанда HTTP-запросов была задокументирована в 2005 году и вновь получила популярность благодаря обширным исследованиям PortSwigger по этой теме. Подробности см. в следующих материалах:

* [HTTP desync attacks: Request smuggling reborn](https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn)
* [HTTP/2: The sequel is always worse](https://portswigger.net/research/http2)
* [Browser-powered desync attacks: A new frontier in HTTP request smuggling](https://portswigger.net/research/browser-powered-desync-attacks)
  {% endhint %}

## Что происходит при атаке контрабанды HTTP-запросов?

Современные веб-приложения часто используют цепочки HTTP-серверов между пользователями и конечной прикладной логикой. Пользователи отправляют запросы на фронтенд-сервер (иногда его называют балансировщиком нагрузки или обратным прокси), и этот сервер пересылает запросы на один или несколько бэкэнд-серверов. Такой тип архитектуры становится всё более распространённым и в некоторых случаях неизбежен в современных облачных приложениях.

Когда фронтенд-сервер пересылает HTTP-запросы на бэкэнд-сервер, он обычно отправляет несколько запросов по одному и тому же бэкэнд-сетевому соединению, поскольку это намного эффективнее и производительнее. Протокол очень прост: HTTP-запросы отправляются один за другим, и принимающий сервер должен определить, где заканчивается один запрос и начинается следующий:

![forwarding-http-requests-to-back-end-server.svg](https://2753068357-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7KQ4F0M3A1jSCGxOdZRW%2Fuploads%2Fgit-blob-85eec4c9f04d41f65d1d6c7e7d291a1db6dadeb1%2Fforwarding-http-requests-to-back-end-server.svg?alt=media)

В этой ситуации крайне важно, чтобы фронтенд и бэкэнд согласованно определяли границы между запросами. Иначе злоумышленник может отправить неоднозначный запрос, который будет интерпретирован фронтендом и бэкэндом по-разному:

![smuggling-http-request-to-back-end-server.svg](https://2753068357-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F7KQ4F0M3A1jSCGxOdZRW%2Fuploads%2Fgit-blob-ff0831b1ec798353669d2c85fea111ef1318f99d%2Fsmuggling-http-request-to-back-end-server.svg?alt=media)

В таком случае злоумышленник заставляет часть своего фронтенд-запроса интерпретироваться бэкэнд-сервером как начало следующего запроса. Фактически эта часть приклеивается к следующему запросу и способна вмешаться в то, как приложение обрабатывает этот запрос. Это и есть атака контрабанды запросов, и её последствия могут быть разрушительными.

## Как возникают уязвимости контрабанды?

Большинство уязвимостей контрабанды HTTP-запросов возникает из-за того, что спецификация HTTP/1 предлагает два разных способа указать, где заканчивается запрос: заголовок `Content-Length` и заголовок `Transfer-Encoding`.

Заголовок `Content-Length` прост: он указывает длину тела сообщения в байтах. Например:

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

q=smuggling
```

Заголовок `Transfer-Encoding` можно использовать, чтобы указать, что тело сообщения применяет блочное кодирование (chunked). Это означает, что тело сообщения содержит один или несколько блоков данных. Каждый блок состоит из размера блока в байтах (в шестнадцатеричном виде), за которым следует перевод строки, затем содержимое блока. Сообщение завершается блоком нулевого размера. Например:

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

b
q=smuggling
0
```

{% hint style="info" %}
**Примечание**

Многие специалисты по безопасности не знают, что блочное (chunked) кодирование может использоваться в HTTP-запросах, по двум причинам:

* Burp Suite автоматически распаковывает chunked-кодирование, чтобы сообщения было легче просматривать и редактировать.
* Браузеры обычно не используют chunked-кодирование в запросах; его обычно видно лишь в ответах сервера.
  {% endhint %}

Поскольку спецификация HTTP/1 предоставляет два разных метода указания длины HTTP-сообщений, одно сообщение может одновременно использовать оба метода, что приведет к конфликту. Спецификация пытается предотвратить эту проблему, заявляя, что если присутствуют и заголовок `Content-Length`, и заголовок `Transfer-Encoding`, то заголовок `Content-Length` следует игнорировать. Этого может быть достаточно, чтобы избежать неоднозначности, когда в работе участвует только один сервер, но не тогда, когда два и более сервера объединены в цепочку. В такой ситуации проблемы могут возникать по двум причинам:

* Некоторые серверы не поддерживают заголовок `Transfer-Encoding` в запросах.
* Некоторые серверы, поддерживающие заголовок `Transfer-Encoding`, можно заставить его не обрабатывать, если заголовок обфусцирован.

Если фронтенд и бэкэнд ведут себя по-разному в отношении (возможно, обфусцированного) заголовка `Transfer-Encoding`, они могут быть не согласованы в границах между запросами, что приводит к уязвимостям контрабанды запросов.

{% hint style="info" %}
**Примечание**

Сайты, использующие HTTP/2 «от конца до конца», по своей природе невосприимчивы к атакам контрабанды запросов. Поскольку спецификация HTTP/2 вводит единый, надёжный механизм указания длины запроса, у злоумышленника нет возможности внести необходимую неоднозначность.

Однако многие сайты имеют фронтенд-сервер, говорящий на HTTP/2, но развёрнутый перед бэкэнд-инфраструктурой, которая поддерживает только HTTP/1. Это означает, что фронтенду фактически приходится преобразовывать получаемые им запросы в HTTP/1. Этот процесс называется понижением версии HTTP (HTTP downgrading). Подробности см. в разделе [Продвинутая контрабанда HTTP-запросов](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/prodvinutaya-kontrabanda-http-zaprosov).
{% endhint %}

## Как выполнить атаку контрабанды

Классические атаки контрабанды запросов предполагают помещение в один HTTP/1 запрос и заголовка `Content-Length`, и заголовка `Transfer-Encoding` и такую их манипуляцию, чтобы фронтенд и бэкэнд обработали запрос по-разному. Точный способ зависит от поведения двух серверов:

* `CL.TE`: фронтенд использует заголовок `Content-Length`, а бэкэнд использует заголовок `Transfer-Encoding`.
* `TE.CL`: фронтенд использует заголовок `Transfer-Encoding`, а бэкэнд использует заголовок `Content-Length`.
* `TE.TE`: и фронтенд, и бэкэнд поддерживают заголовок `Transfer-Encoding`, но один из серверов можно заставить его не обрабатывать, обфусцируя заголовок определённым образом.

{% hint style="info" %}
**Примечание**

Эти приёмы возможны только с запросами HTTP/1. Браузеры и другие клиенты, включая Burp, по умолчанию используют HTTP/2 для связи с серверами, которые явно объявляют поддержку HTTP/2 во время TLS-рукопожатия.

В результате при тестировании сайтов с поддержкой HTTP/2 вам нужно вручную переключить протокол в Burp Repeater. Это можно сделать в разделе **Request attributes** панели **Inspector**.
{% endhint %}

### Уязвимости типа CL.TE

Здесь фронтенд использует заголовок `Content-Length`, а бэкэнд — заголовок `Transfer-Encoding`. Можно выполнить простую атаку контрабанды следующим образом:

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

0

SMUGGLED
```

Фронтенд-сервер обрабатывает заголовок `Content-Length` и определяет, что тело запроса имеет длину 13 байт — до конца `SMUGGLED`. Этот запрос перенаправляется на бэкэнд-сервер. Бэкэнд-сервер обрабатывает заголовок `Transfer-Encoding` и, следовательно, трактует тело сообщения как использующее блочное (chunked) кодирование. Он обрабатывает первый блок, чей размер указан как нулевой, и, следовательно, воспринимает это как завершение запроса. Последующие байты, `SMUGGLED`, остаются необработанными, и бэкэнд-сервер воспримет их как начало следующего запроса в последовательности.

{% hint style="success" %}
**LAB**

[**HTTP request smuggling, basic CL.TE vulnerability**](https://portswigger.net/web-security/request-smuggling/lab-basic-cl-te)
{% endhint %}

### Уязвимости типа TE.CL

Здесь фронтенд использует заголовок `Transfer-Encoding`, а бэкэнд — заголовок `Content-Length`. Можно выполнить простую атаку контрабанды следующим образом:

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

8
SMUGGLED
0
```

{% hint style="info" %}
**Примечание**

Чтобы отправить этот запрос с помощью Burp Repeater, сначала откройте меню Repeater и убедитесь, что опция «Update Content-Length» отключена.

Необходимо добавить завершающую последовательность `\r\n\r\n` сразу после последнего `0`.
{% endhint %}

Фронтенд-сервер обрабатывает заголовок `Transfer-Encoding` и, следовательно, трактует тело сообщения как использующее блочное кодирование. Он обрабатывает первый блок, чей размер указан как 8 байт, до начала строки, следующей за `SMUGGLED`. Затем он обрабатывает второй блок, чей размер равен нулю, и воспринимает это как завершение запроса. Этот запрос пересылается на бэкэнд-сервер.

Бэкэнд-сервер обрабатывает заголовок `Content-Length` и определяет, что тело запроса имеет длину 3 байта — до начала строки, следующей за `8` \[*после символа `8` идут два непечатаемых символа `\r\n`*]. Последующие байты, начиная с `SMUGGLED`, остаются необработанными, и бэкэнд-сервер воспримет их как начало следующего запроса в последовательности.

{% hint style="success" %}
**LAB**

[**HTTP request smuggling, basic TE.CL vulnerability**](https://portswigger.net/web-security/request-smuggling/lab-basic-te-cl)
{% endhint %}

### Поведение TE.TE: обфускация заголовка TE

Здесь и фронтенд, и бэкэнд поддерживают заголовок `Transfer-Encoding`, но один из серверов можно заставить его не обрабатывать, обфусцировав заголовок тем или иным образом.

Способов обфусцировать заголовок `Transfer-Encoding` потенциально бесконечное множество. Например:

```
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
```

Каждый из этих приёмов предполагает тонкое отступление от спецификации HTTP. Реальный код, реализующий протокол, редко следует спецификации с абсолютной точностью, и разные реализации обычно по-разному терпимо относятся к отклонениям. Чтобы обнаружить уязвимость TE.TE, необходимо найти такой вариант заголовка `Transfer-Encoding`, при котором только один из серверов (фронтенд или бэкэнд) его обработает, а другой проигнорирует.

В зависимости от того, можно ли заставить игнорировать обфусцированный заголовок `Transfer-Encoding` фронтенд или бэкэнд, остальная часть атаки примет ту же форму, что и для уязвимостей CL.TE или TE.CL, описанных выше.

{% hint style="success" %}
**LAB**

[**HTTP request smuggling, obfuscating the TE header**](https://portswigger.net/web-security/request-smuggling/lab-obfuscating-te-header)
{% endhint %}

## Как выявить уязвимости контрабанды

Обратитесь к следующему разделу за советами о том, как самостоятельно выявлять уязвимости контрабанды HTTP-запросов.

{% hint style="info" %}
**Подробнее**

[Поиск уязвимостей контрабанды HTTP-запросов](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/poisk-uyazvimostei-kontrabandy-http-zaprosov)
{% endhint %}

## Как эксплуатировать уязвимости контрабанды

Теперь, когда вы знакомы с базовыми концепциями, давайте посмотрим, как контрабанда HTTP-запросов может использоваться для построения ряда атак высокой степени критичности.

{% hint style="info" %}
**Подробнее**

[Эксплуатация уязвимостей контрабанды HTTP-запросов](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/ekspluataciya-uyazvimostei-kontrabandy-http-zaprosov)
{% endhint %}

## Продвинутая контрабанда

Если вы уже прошли остальные лабораторные задания по контрабанде запросов, вы готовы изучить более продвинутые техники.

{% hint style="info" %}
**Подробнее**

[Продвинутая контрабанда HTTP-запросов](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/prodvinutaya-kontrabanda-http-zaprosov)
{% endhint %}

## Контрабанда запросов на стороне браузера

Описанные вами до сих пор техники контрабанды запросов опираются на отправку намеренно некорректных запросов с помощью специализированных инструментов, таких как Burp Repeater. На самом деле те же атаки можно выполнить с использованием полностью совместимых с браузером запросов, которые рассинхронизируют два сервера посредством совершенно обычного заголовка `Content-Length`.

Это даже позволяет запускать варианты этих атак на стороне клиента, когда браузер жертвы отравляет собственное соединение с уязвимым сайтом. Это не только открывает одиночные серверные сайты для атак в стиле контрабанды запросов, но и позволяет атаковать сайты, к которым у вас нет прямого доступа.

{% hint style="info" %}
**Подробнее**

[Контрабанда запросов на стороне браузера](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/kontrabanda-zaprosov-na-storone-brauzera)
{% endhint %}

## Как предотвратить уязвимости контрабанды HTTP-запросов

Уязвимости контрабанды HTTP-запросов возникают в ситуациях, когда фронтенд-сервер и бэкэнд-сервер используют разные механизмы для определения границ между запросами. Это может быть связано с расхождениями в том, используют ли серверы HTTP/1 заголовок `Content-Length` или блочное кодирование для определения конца каждого запроса. В средах HTTP/2 распространённая практика [понижения версии HTTP-2](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/prodvinutaya-kontrabanda-http-zaprosov/ponizhenie-versii-http-2-http-2-downgrading) для бэкэнда также чревата проблемами и включает или упрощает ряд дополнительных атак.

Чтобы предотвратить уязвимости контрабанды HTTP-запросов, используйте следующие рекомендации:

* Используйте HTTP/2 сквозным образом (end to end) и по возможности отключайте понижение версии HTTP. HTTP/2 применяет надёжный механизм определения длины запросов и, при сквозном использовании, защищён от контрабанды запросов. Если избежать понижения версии нельзя, валидируйте переписанный запрос в соответствии со спецификацией HTTP/1.1. Например, отклоняйте запросы, содержащие переводы строки в заголовках, двоеточия в именах заголовков и пробелы в методе запроса.
* Заставьте фронтенд-сервер нормализовать неоднозначные запросы, а бэкэнд-сервер — отклонять любые, которые остаются неоднозначными, при этом закрывая TCP-соединение.
* Никогда не предполагайте, что у запросов не будет тела. Это фундаментальная причина уязвимостей как CL.0, так и клиентских десинхронизаций.
* По умолчанию разрывайте соединение, если при обработке запросов срабатывают исключения на уровне сервера.
* Если вы маршрутизируете трафик через прямой прокси (forward proxy), по возможности убедитесь, что включён upstream HTTP/2.

Как показано в учебных материалах, отключение повторного использования соединений с бэкэндом помогает смягчить некоторые виды атак, но это всё равно не защищает от атак [туннелирования запросов](https://wr3dmast3r.gitbook.io/portswiggerfundamental/advanced/http-request-smuggling/prodvinutaya-kontrabanda-http-zaprosov/tunnelirovanie-http-zaprosov-http-request-tunnelling).

{% hint style="info" %}
**Подробнее**

* [Find HTTP request smuggling vulnerabilities using Burp Suite's web vulnerability scanner](https://portswigger.net/burp/vulnerability-scanner)
  {% endhint %}
