HTTP request smuggling

http-request-smuggling

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

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

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

Исследования PortSwigger

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

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

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

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

forwarding-http-requests-to-back-end-server.svg

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

smuggling-http-request-to-back-end-server.svg

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

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

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

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

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

Примечание

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

  • Burp Suite автоматически распаковывает chunked-кодирование, чтобы сообщения было легче просматривать и редактировать.

  • Браузеры обычно не используют chunked-кодирование в запросах; его обычно видно лишь в ответах сервера.

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

  • Некоторые серверы не поддерживают заголовок Transfer-Encoding в запросах.

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

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

Примечание

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

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

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

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

  • CL.TE: фронтенд использует заголовок Content-Length, а бэкэнд использует заголовок Transfer-Encoding.

  • TE.CL: фронтенд использует заголовок Transfer-Encoding, а бэкэнд использует заголовок Content-Length.

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

Примечание

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

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

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

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

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

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

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

Примечание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Уязвимости контрабанды HTTP-запросов возникают в ситуациях, когда фронтенд-сервер и бэкэнд-сервер используют разные механизмы для определения границ между запросами. Это может быть связано с расхождениями в том, используют ли серверы HTTP/1 заголовок Content-Length или блочное кодирование для определения конца каждого запроса. В средах HTTP/2 распространённая практика понижения версии HTTP-2 для бэкэнда также чревата проблемами и включает или упрощает ряд дополнительных атак.

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

  • Используйте HTTP/2 сквозным образом (end to end) и по возможности отключайте понижение версии HTTP. HTTP/2 применяет надёжный механизм определения длины запросов и, при сквозном использовании, защищён от контрабанды запросов. Если избежать понижения версии нельзя, валидируйте переписанный запрос в соответствии со спецификацией HTTP/1.1. Например, отклоняйте запросы, содержащие переводы строки в заголовках, двоеточия в именах заголовков и пробелы в методе запроса.

  • Заставьте фронтенд-сервер нормализовать неоднозначные запросы, а бэкэнд-сервер — отклонять любые, которые остаются неоднозначными, при этом закрывая TCP-соединение.

  • Никогда не предполагайте, что у запросов не будет тела. Это фундаментальная причина уязвимостей как CL.0, так и клиентских десинхронизаций.

  • По умолчанию разрывайте соединение, если при обработке запросов срабатывают исключения на уровне сервера.

  • Если вы маршрутизируете трафик через прямой прокси (forward proxy), по возможности убедитесь, что включён upstream HTTP/2.

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

Last updated