Эксплуатация контрабанды запросов

Использование контрабанды для обхода механизмов безопасности на фронтенде

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

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

Предположим, текущему пользователю разрешён доступ к /home, но не к /admin. Он может обойти это ограничение следующей атакой контрабанды:

POST /home HTTP/1.1
Host: vulnerable-website.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 62
Transfer-Encoding: chunked

0

GET /admin HTTP/1.1
Host: vulnerable-website.com
Foo: xGET /home HTTP/1.1
Host: vulnerable-website.com
front-end
  1. POST /home HTTP/1.1
    Host: vulnerable-website.com
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 62
    Transfer-Encoding: chunked
    
    0
    
    GET /admin HTTP/1.1
    Host: vulnerable-website.com
    Foo: x
  2. GET /home HTTP/1.1
    Host: vulnerable-website.com
back-end

Фронтенд-сервер видит здесь два запроса, оба к /home, и пересылает их на бэкэнд-сервер. Однако бэкэнд-сервер видит один запрос к /home и один к /admin. Он как обычно предполагает, что запросы прошли фронтенд-контроль, и предоставляет доступ к ограниченному URL.

Раскрытие переписывания запросов на фронтенде

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

  • завершать TLS-соединение и добавлять заголовки, описывающие использованные протокол и шифры;

  • добавлять заголовок X-Forwarded-For с IP-адресом пользователя;

  • определять ID пользователя по его сессионному токену и добавлять заголовок, идентифицирующий пользователя;

  • добавлять некоторую чувствительную информацию, представляющую интерес для других атак.

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

  • Найти POST-запрос, который отражает значение параметра запроса в ответе приложения.

  • Переставить параметры так, чтобы отражаемый параметр располагался последним в теле сообщения.

  • Использовать контрабанду, чтобы провезти этот запрос на бэкэнд-сервер, сразу за ним поместив обычный запрос, переписанную форму которого вы хотите увидеть.

Предположим, что у приложения есть функция входа, которая отражает значение параметра email:

Это приводит к ответу, содержащему следующее:

Здесь вы можете использовать следующую атаку контрабанды, чтобы раскрыть переписывание, выполняемое фронтенд-сервером:

Запросы будут переписаны фронтенд-сервером с добавлением дополнительных заголовков, после чего бэкэнд-сервер обработает контрабандный запрос и воспримет переписанный второй запрос как значение параметра email. Затем он отразит это значение в ответе на второй запрос:

Примечание

Поскольку финальный запрос переписывается, вы не знаете, какой длины он окажется. Значение заголовка Content-Length в контрабандном запросе определяет, какой длины бэкэнд-сервер будет считать тело запроса. Если вы зададите слишком маленькое значение, получите только часть переписанного запроса; если слишком большое — бэкэнд-сервер будет ждать завершения запроса и в итоге отдаст таймаут. Разумное решение — угадать начальное значение немного больше отправленного запроса и постепенно увеличивать его, чтобы получить больше информации, пока вы не соберёте всё интересующее.

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

Обход аутентификации клиента

В составе TLS-рукопожатия серверы аутентифицируются перед клиентом (обычно браузером), предоставляя сертификат. Этот сертификат содержит CN, которое должно соответствовать их зарегистрированному хостнейму. Клиент может использовать это для проверки того, что он общается с легитимным сервером ожидаемого домена.

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

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

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

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

Перехват запросов других пользователей

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

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

Рассмотрим, что произойдёт, если вы провезёте эквивалентный запрос с чрезмерно большим заголовком Content-Length и расположите параметр comment в конце запроса, как показано ниже:

Заголовок Content-Length контрабандного запроса указывает, что тело будет длиной 400 байт, но мы отправили лишь 144 байта. В этом случае бэкэнд-сервер будет ждать оставшиеся 256 байт перед выдачей ответа, либо выдаст таймаут, если они не поступят достаточно быстро. В результате, когда по тому же соединению на бэкэнд-сервер поступит следующий запрос, первые 256 байт фактически присоединятся к контрабандному запросу следующим образом:

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

Чтобы перехватить больше содержимого запроса жертвы, просто увеличьте значение заголовка Content-Length контрабандного запроса, но учтите, что это будет связано с определённой долей проб и ошибок. Если вы сталкиваетесь с таймаутом, скорее всего, указанный Content-Length больше фактической длины запроса жертвы. В этом случае просто уменьшайте значение, пока атака снова не сработает.

Примечание

Одно ограничение этой техники состоит в том, что, как правило, удаётся захватить данные лишь до разделителя параметров, применимого к контрабандному запросу. Для отправки форм в URL-кодировке таким разделителем является символ &, то есть сохранённое содержимое из запроса пользователя-жертвы завершится на первом &, который может встречаться даже в строке запроса.

Использование контрабанды для эксплуатации reflected XSS

Если приложение уязвимо к контрабанде HTTP-запросов и при этом содержит reflected XSS, вы можете использовать контрабанду, чтобы воздействовать на других пользователей приложения. Этот подход превосходит обычную эксплуатацию reflected XSS двумя способами:

  • Он не требует взаимодействия с жертвами. Не нужно подсовывать им URL и ждать перехода. Вы просто провозите запрос с XSS пейлоадом, и следующий запрос, обработанный бэкэнд-сервером, будет поражён.

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

Например, предположим, что в приложении есть уязвимость reflected XSS в заголовке User-Agent. Вы можете эксплуатировать её в атаке контрабанды следующим образом:

Следующий пользовательский запрос будет присоединён к контрабандному, и в ответе он получит XSS пейлоад.

Использование контрабанды для превращения on-site redirect в open redirect

Многие приложения выполняют внутрисайтовые перенаправления и подставляют хостнейм из заголовка Host в URL редиректа. Примером этого является поведение веб-серверов Apache и IIS по умолчанию: запрос к каталогу без завершающего слэша получает редирект на тот же каталог, но уже со слэшем:

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

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

Здесь пользователь запрашивал JavaScript-файл, подключаемый страницей сайта. Злоумышленник может полностью скомпрометировать пользователя, вернув в ответе собственный JavaScript.

Преобразование root-relative redirect в open redirect

Иногда вы можете столкнуться с редиректами на уровне сервера, которые используют путь для построения URL относительно корня в заголовке Location, например:

Такой редирект потенциально тоже можно превратить в открытый, если сервер позволяет использовать URL с относительным протоколом в пути:

Использование контрабанды для отравления веб-кэша

В разновидности предыдущей атаки может оказаться возможным использовать контрабанду для проведения атаки Web Cache Poisoning. Если какая-либо часть фронтенд-инфраструктуры кэширует контент (обычно в целях производительности), может оказаться возможным отравить кэш ответом с редиректом на внешний сайт. Это будет влиять на любого пользователя, который затем запросит затронутый URL.

В этом варианте злоумышленник отправляет на фронтенд-сервер следующее:

Контрабандный запрос достигает бэкэнд-сервера, который, как и ранее, отвечает редиректом на внешний сайт. Фронтенд-сервер кэширует этот ответ на тот URL, который, как он считает, содержится во втором запросе, а именно /static/include.js:

С этого момента, когда другие пользователи запрашивают этот URL, они получают редирект на сайт злоумышленника.

Использование контрабанды для обмана веб-кэша

В ещё одной разновидности атаки вы можете использовать контрабанду для проведения атаки Web Cache Deception. Она схожа с атакой Web Cache Poisoning, но преследует другую цель.

В чём разница между отравлением и обманом веб-кэша?

  • При отравлении веб-кэша злоумышленник заставляет приложение сохранить в кэше вредоносный контент, который затем раздаётся другим пользователям приложения.

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

В этом варианте злоумышленник провозит запрос, который возвращает некоторый чувствительный, привязанный к пользователю контент. Например:

Следующий запрос другого пользователя, который будет переслан на бэкэнд-сервер, присоединится к контрабандному запросу, включая сессионные cookie и другие заголовки. Например:

Бэкэнд-сервер отвечает на этот запрос обычным образом. URL запроса указывает на личные сообщения пользователя, и запрос обрабатывается в контексте сессии жертвы. Фронтенд-сервер кэширует этот ответ на тот URL, который, как он считает, содержится во втором запросе, то есть /static/some-image.png:

Затем злоумышленник посещает статический URL и получает чувствительный контент, который возвращается из кэша.

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

Last updated