В цепочке прокси и приложения один HTTP-запрос может иметь две разные границы тела. Какой риск должен подтвердить тестировщик?
Тестировщик должен подтвердить или опровергнуть HTTP Request Smuggling — возможность сформировать запрос, который прокси и сервер приложения разбирают по-разному. Это может позволить спрятать дополнительный запрос внутри соединения, повлиять на запрос другого пользователя или обойти контроль доступа на уровне прокси.
Подход появился из-за того, что HTTP-запросы часто проходят через несколько компонентов: балансировщики, reverse proxy, WAF и сервер приложения. Если эти компоненты используют разные правила определения границы тела запроса, один поток байтов получает неодинаковый смысл на разных этапах.
Проблема особенно характерна для HTTP/1.1, где граница тела может задаваться разными механизмами. Современные реализации обычно стараются отклонять неоднозначные запросы, но безопасность зависит от всей цепочки, а не только от одного сервера.
Риск возникает, когда фронтенд учитывает один заголовок длины тела, а бэкенд — другой либо по-разному обрабатывает конфликтующие заголовки. Тогда фронтенд может считать запрос завершённым, а приложение — продолжить чтение оставшихся байтов как нового запроса.
Последствия зависят от архитектуры: обход правил WAF, обращение к внутренним endpoint, нарушение привязки запросов к пользователям, отравление очереди запросов и кража части следующего ответа. Проверку нельзя выполнять на общем продуктивном соединении: некорректный тест способен повлиять на запросы других пользователей.
Тестировщик сначала описывает цепочку обработки: какие прокси стоят перед приложением, используется ли повторное применение TCP-соединений, где завершается TLS и какой компонент устанавливает границу тела. Затем безопасно проверяет, одинаково ли компоненты отклоняют неоднозначные запросы.
Типовой признак — конфликт между двумя способами указать длину тела или наличие нескольких значений одного управляющего заголовка. Например, тестовый запрос может содержать противоречивые сведения о длине:
Этот пример нельзя без адаптации отправлять в продуктивную среду. В безопасном стенде наблюдают, видит ли приложение отдельный запрос к /marker, появляется ли задержка или меняется ли ответ следующего контролируемого запроса. Доказательством уязвимости является воспроизводимая разница в разборе между компонентами, подтверждённая логами или уникальным безопасным маркером.
Защита состоит в устранении неоднозначности: фронтенд должен отклонять конфликтующие или повторные управляющие заголовки, нормализовать запрос единственным способом и передавать дальше уже однозначно разобранное сообщение. Важно также согласовать версии прокси и приложения и не полагаться только на WAF: фильтр, который сам разбирает запрос иначе, может стать частью проблемы.
В тестовой среде WAF пропускал запросы с одновременно заданными параметрами длины, а сервер приложения обрабатывал их по другому правилу. Вариант с отправкой теста через общий балансировщик был отклонён: он мог повлиять на соседние соединения. Вариант с проверкой только HTTP-кодов оказался недостаточным, поскольку одинаковый код не доказывает одинаковый разбор.
Команда создала изолированный стенд с теми же версиями прокси и приложения, добавила уникальный маркер в безопасный endpoint и сопоставила сетевые трассы с журналами обоих компонентов. Было установлено, что прокси завершал внешний запрос раньше приложения, а оставшиеся байты сервер интерпретировал отдельно. Решением стало отклонение неоднозначных запросов на внешнем прокси и обновление компонента, после чего повторный тест показал единый отказ до передачи запроса приложению.
1. Достаточно ли увидеть конфликтующие заголовки, чтобы доказать уязвимость?
Нет. Конфликт — это индикатор неоднозначности, но не доказательство успешного рассинхрона. Нужно показать различие в обработке между компонентами с безопасным маркером, не затрагивая реальные пользовательские запросы.
2. Чем опасна проверка только по ответу на отправленный запрос?
Основной эффект может проявиться не в его собственном ответе, а в обработке следующего запроса по тому же соединению. Поэтому необходимо учитывать повторное использование соединений, порядок запросов, сетевые трассы и журналы прокси и приложения. Иначе тест может ошибочно объявить систему безопасной.
3. Почему исправление только на сервере приложения может быть недостаточным?
Если внешний прокси уже по-другому разобрал поток, приложение получает не исходный запрос, а результат ошибочного разделения. Серверное отклонение снижает часть риска, но не устраняет рассинхрон между компонентами. Надёжнее сделать границы однозначными на первом доверенном узле и проверить одинаковое поведение всей цепочки.