Векторы, эксклюзивные для HTTP-2

Из-за того, что HTTP/2 — бинарный протокол, а не текстовый, существует ряд потенциальных векторов, которые невозможно сконструировать в HTTP/1 из-за ограничений его синтаксиса.

Мы уже видели, как можно внедрить CRLF в значение заголовка. В этом разделе мы покажем некоторые другие векторы, эксклюзивные для HTTP/2, которые вы можете использовать для внедрения полезных нагрузок. Хотя такие запросы официально запрещены спецификацией HTTP/2, некоторые серверы не справляются с их корректной валидацией и блокированием.

Note

Выполнить эти атаки возможно только с помощью специализированных функций HTTP/2 в панели Inspector Burp.

Внедрение через имена заголовков

В HTTP/1 имя заголовка не может содержать двоеточие, поскольку этот символ используется парсерами для обозначения конца имени. В HTTP/2 это ограничение отсутствует.

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

Front-end (HTTP/2)

foo: bar\r\nTransfer-Encoding: chunked\r\nX:

ignore

Back-end (HTTP/1)

Foo: bar\r\n
Transfer-Encoding: chunked\r\n
X: ignore\r\n

Внедрение через псевдозаголовки

HTTP/2 не использует строку запроса или строку статуса. Вместо этого эти данные передаются через серию псевдозаголовков в начале запроса. В текстовых представлениях сообщений HTTP/2 они обычно помечаются префиксом из двоеточия, чтобы отличать их от обычных заголовков. Всего существует пять псевдозаголовков:

  • :method — метод запроса.

  • :path — путь запроса. Обратите внимание, что он включает query string.

  • :authority — приблизительный эквивалент заголовка Host в HTTP/1.

  • :scheme — схема запроса, обычно http или https.

  • :status — код статуса ответа (в запросах не используется).

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

Задание неоднозначного хоста

Хотя HTTP/1 заголовок Host фактически заменяется псевдозаголовком :authority в HTTP/2, вы всё равно можете отправить в запросе и заголовок host.

В некоторых случаях это может привести к появлению двух заголовков Host в переписанном HTTP/1-запросе, что, например, открывает возможность обхода фронтенд-фильтров “duplicate Host header”. Это потенциально делает сайт уязвимым к ряду атак на заголовок Host, от которых он ранее мог быть защищён.

Задание неоднозначного пути

Попытка отправить запрос с неоднозначным path невозможна в HTTP/1 из-за того, как парсится строка запроса. Но поскольку путь в HTTP/2 задаётся псевдозаголовком, теперь можно отправить запрос с двумя различными путями следующим образом:

:method

POST

:path

/anything

:path

/admin

:authority

vulnerable-website.com

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

Внедрение полной строки запроса

При понижении версии значение псевдозаголовка :method записывается в самое начало результирующего запроса HTTP/1. Если сервер позволяет вам включать пробелы в значение :method, вы можете внедрить совершенно иную строку запроса, как показано ниже:

Front-end (HTTP/2)

:method

GET /admin HTTP/1.1

:path

/anything

:authority

vulnerable-website.com

Back-end (HTTP/1)

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

Внедрение префикса URL

Ещё одна интересная особенность HTTP/2 — возможность явно задавать схему в самом запросе с помощью псевдозаголовка :scheme. Хотя обычно он содержит лишь http или https, вы можете попытаться включить произвольные значения.

Это может быть полезно, когда сервер, например, использует :scheme для динамической генерации URL. В этом случае вы можете добавить префикс к URL или даже полностью его переопределить, вписав настоящий URL в строку запроса:

Request

:method

GET

:path

/anything

:authority

vulnerable-website.com

:scheme

https://evil-user.net/poison?

Response

:status

301

location

https://evil-user.net/poison?://vulnerable-website.com/anything/

Вставка перевода строки в псевдозаголовки

При внедрении в псевдозаголовки :path или :method необходимо убедиться, что результирующий запрос HTTP/1 по-прежнему имеет корректную строку запроса.

Поскольку в HTTP/1 последовательность \r\n завершает строку запроса, простое добавление \r\n посередине просто сломает запрос. После понижения переписанный запрос должен содержать следующую последовательность до первой вставленной вами \r\n:

Просто визуализируйте, где именно ваша вставка попадает в эту последовательность, и включайте все оставшиеся части соответствующим образом. Например, при внедрении в :path вам нужно добавить пробел и HTTP/1.1 перед \r\n, как показано ниже:

Front-end (HTTP/2)

:method

GET

:path

:authority

vulnerable-website.com

Back-end (HTTP/1)

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

Last updated