Уязвимости в проекте Pingora, позволяющие вклиниться в сторонние запросы

Компания Cloudflare объявила об устранении трёх уязвимостей во фреймворке Pingora, двум из которых присвоен критический уровень опасности (9.3 из 10). Фреймворк Pingora написан на языке Rust и предназначен для разработки защищённых высокопроизводительных сетевых сервисов. Построенный при помощи Pingora прокси используется в сети доставки контента Cloudflare и обрабатывает более 40 млн запросов в секунду. Уязвимости устранены в выпуске Pingora 0.8.0.

Две наиболее опасные уязвимости допускают проведение атак класса «HTTP Request Smuggling«, позволяющих обходить системы ограничения доступа и вклиниваться в содержимое запросов других пользователей, обрабатываемых в том же потоке между фронтэндом и бэкендом (например, для подстановки вредоносного JavaScript-кода в сеанс другого пользователя с сайтом). Проблемы выявлены участником программы Bug Bounty, предусматривающей выплату вознаграждения за обнаружение уязвимостей.

В схеме с обращением к бэкенду через обратный прокси запросы клиентов принимает дополнительный узел, который устанавливает длительно действующее TCP-соединение с бэкендом, осуществляющим непосредственную обработку запросов. Через данное общее соединение обычно передаются запросы разных пользователей, которые следуют по цепочке один за другим с разделением средствами протокола HTTP.
Атаки класса HTTP Request Smuggling возникают из-за разной трактовки HTTP-заголовков и спецификаций протокола HTTP на фронтэндах и бэкендах, например, когда фронтэнд использует для определения размера запроса HTTP-заголовок «Content-Length», а бэкенд «Transfer-Encoding: chunked».

Первая уязвимость CVE-2026-2835 присутствует в коде разбора запросов HTTP/1.0 и вызвана некорректной обработкой заголовка «Transfer-Encoding» с несколькими значениями, а также использованием закрытия соединения как признака конца тела запроса (close-delimited). Pingora проверял только вариант «Transfer-Encoding: chunked» и игнорировал данный заголовок, если в нём указывалось несколько значений. В этой ситуации Pingora не учитывал размер в заголовке «Content-Length», а считал телом запроса все данные, полученные до закрытия соединения.

Через указание нескольких значений в заголовке «Transfer-Encoding» атакущий мог создать условия, при которых на бэкенд перенаправлялся запрос, фактический размер которого не соответствовал размеру chunked-цепочки, вычисленному на основе заголовка «Transfer-Encoding. Pingora перенаправлял все полученные данные как один запрос, а бэкенд, например, Node.js, вычислял запрос на основе «Transfer-Encoding: chunked» и оставшийся хвост обрабатывал как начало другого запроса.


   GET / HTTP/1.0
   Host: example.com
   Connection: keep-alive
   Transfer-Encoding: identity, chunked
   Content-Length: 29

   0

   GET /admin HTTP/1.1
   X:

Вторая уязвимость CVE-2026-2833 вызвана некорректной обработкой HTTP-заголовка «Upgrade» в запросах HTTP/1.1. При наличии в запросе заголовка «Upgrade» прокси сразу пробрасывал к бэкенду и остальные данные запроса, следующие за заголовком «Upgrade», не дожидаясь от бэкенда ответа с кодом 101 (Switching Protocols). Из-за этого синхронизация потока между прокси и бэкендом нарушалась и бэкенд воспринимал отправленные после заголовка «Upgrade» данные как отдельный запрос, и отправлял результат выполнения этого запроса в ответ на пришедший следом запрос другого пользователя.


   GET / HTTP/1.1
   Host: example.com
   Upgrade: foo


   GET /admin HTTP/1.1
   Host: example.com

Проблемы проявляются при использовании Pingora в форме обратного прокси (ingress proxy), транслирующего запросы пользователей к бэкендам с использованием протоколов HTTP/1.0 или HTTP/1.1. Применяемая в сети доставки контента Cloudflare конфигурация Pingora не позволяла эксплуатировать уязвимости, так как Pingora в CDN не используется в роли ingress-прокси, перенаправляет запросы только с использованием протокола HTTP/1.1, блокирует запросы с некорректными значениями Content-Length, перенаправляет только одно значение заголовка «Transfer-Encoding: chunked» и подставляет в запросы с заголовком «Upgrade:» дополнительный заголовок «Connection: close», не позволяющий передавать дополнительные запросы в том же соединении.

Третья уязвимость CVE-2026-2836 (степень опасности 8.4 из 10) приводит к отравлению кэша (cache poisoning) из-за генерации ключа размещения данных в кэше (CacheKey) только на основе пути из URI, игнорируя содержимое заголовка «Host». Подобная недоработка приводит к формированию одинаковых ключей кэширования для одинаковых HTTP-путей к разным хостам. Уязвимость может использоваться для подмены содержимого кэша при использовании режима кэширования для нескольких хостов. В Pingora кэширование является экспериментальной функцией, не рекомендованной для рабочих внедрений.

Источник: http://www.opennet.ru/opennews/art.shtml?num=64957