Прокси и приложение по разному определяют границу одного HTTP запроса. Какой риск возникает на такой границе?

Прокси и приложение по-разному определяют границу одного HTTP-запроса. Какой риск возникает на такой границе?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Возникает риск HTTP request smuggling — контрабанды HTTP-запросов. Атакующий формирует сообщение, которое прокси и приложение разбирают по-разному, из-за чего часть данных может быть воспринята как отдельный запрос и попасть к следующему обработчику или пользователю.

Исторический контекст

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

Проблема особенно проявлялась при неоднозначном сочетании Content-Length и Transfer-Encoding, повторяющихся заголовках длины или переходе между HTTP/2 и HTTP/1.1. Различия в разборе превращали сетевую границу в источник рассинхронизации.

Постановка проблемы

Если прокси считает, что запрос заканчивается в одной позиции, а приложение — в другой, TCP-поток может быть интерпретирован двумя способами. Остаток данных, который прокси считает частью уже обработанного сообщения, приложение способно принять за начало следующего запроса.

Последствия включают обход правил WAF или маршрутизации, отправку подготовленного запроса перед запросом жертвы, доступ к чужому ответу, обход ограничений доступа и нарушение изоляции между клиентами. Даже если само приложение корректно проверяет авторизацию, атака на рассинхронизацию может изменить то, какой запрос оно фактически получит.

Подробное решение

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

Важно, чтобы фронтенд и приложение использовали согласованные правила разбора. Надёжнее нормализовать запрос в одном доверенном компоненте, удалить неоднозначность и передавать дальше уже однозначное представление, чем полагаться на совпадение поведения независимых HTTP-парсеров.

При проксировании между версиями протокола необходимо отдельно проверять преобразование HTTP/2 в HTTP/1.1. Механизм, безопасный для HTTP/2, не устраняет автоматически риски в компоненте, который формирует HTTP/1.1-сообщение. Также следует ограничивать повторное использование соединений после подозрительных ошибок разбора и регулярно тестировать фактическое поведение всей цепочки, а не только отдельного прокси.

Полностью запретить повторное использование соединений — простой, но дорогой способ снизить часть последствий: он ухудшает производительность и не исправляет саму неоднозначность. Основная мера — единые строгие правила парсинга и отказ от неоднозначных сообщений.

Ситуация из практики

В системе перед приложением стояли CDN, WAF и reverse proxy. WAF принимал запрос, ориентируясь на один заголовок длины, а внутренний прокси передавал тот же поток приложению с другой интерпретацией. Атакующий мог подготовить префикс следующего запроса так, чтобы он оказался перед запросом другого клиента на общем соединении.

Рассматривались три варианта. Отключение keep-alive уменьшало вероятность влияния на следующий запрос, но заметно ухудшало задержки и пропускную способность. Полный отказ от HTTP/2 устранял конкретный путь преобразования, но не решал неоднозначность HTTP/1.1. Выбранное решение включало строгий отказ от конфликтующих заголовков на внешнем прокси, одинаковую политику парсинга на всех узлах и отдельные тесты для переходов между версиями протокола.

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

Что кандидаты часто упускают

  1. Достаточно ли настроить только WAF?

Нет. WAF может корректно отклонять запрос согласно собственному парсеру, но если другой прокси или приложение трактуют поток иначе, уязвимость останется на следующем участке. Проверять нужно всю последовательность компонентов и преобразований, включая балансировщики и переходы между версиями HTTP.

  1. Почему проверка авторизации в приложении не гарантирует защиту?

Авторизация проверяет уже разобранный запрос и его параметры. При request smuggling приложение может получить другой запрос, чем тот, который видел фильтр, либо обработать внедрённый запрос в контексте другого соединения. Поэтому корректная авторизация необходима, но не заменяет однозначный сетевой разбор.

  1. Можно ли безопасно принимать одновременно Content-Length и Transfer-Encoding?

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