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

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

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

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

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

Категории

Все категории
Loading categories
HTTP3ONSTEROIDS — HTTP3ONSTEROIDS - A research on CVE-2023-25950 where HAProxy's HTTP/3 implementation fails to block a malformed HTTP header field name. | Kitploit
Инструменты/GitHubGitHub/dhmosfunk/http3onsteroids
Vulnerability AnalysisWeb Application ExploitationLearning & EducationLabs & Practice
GitHubdhmosfunk/http3onsteroids

HTTP3ONSTEROIDS

HTTP3ONSTEROIDS - A research on CVE-2023-25950 where HAProxy's HTTP/3 implementation fails to block a malformed HTTP header field name.

Репозиторий
1121 год назадЕщё не проверено

Популярное

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

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

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

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

Смотреть все инструменты →
Поделиться

Содержание

  • Описание уязвимости
    • Обзор исходного кода
  • Настройка лаборатории
    • Выявление проблемы
  • Ссылки

Описание уязвимости

Реализация HTTP/3 в HAProxy не блокирует некорректное имя поля HTTP-заголовка, и при развёртывании перед сервером, который неправильно обрабатывает такой некорректный заголовок, это может быть использовано для проведения атаки по подмене HTTP-запроса/ответа. Удалённый злоумышленник может изменить легитимный запрос пользователя. В результате злоумышленник может получить конфиденциальную информацию или вызвать состояние отказа в обслуживании (DoS).

https://jvn.jp/en/jp/JVN38170084/

Обзор исходного кода

Очень хороший подход перед началом любого исследования CVE — начать с чтения описания уязвимости, а затем проверить, доступны ли коммиты с исправлениями.
В моём случае коммит был доступен, и очевидно, что разработчики HAProxy забыли включить проверки, указанные в RFC 9114 4.1.2. Malformed Requests and Responses, во время разбора стандартных заголовков в реализации HTTP3.

См. коммит с исправлением ниже.

root@kitploit:~
--- a/src/h3.c
+++ b/src/h3.c
@@ -352,7 +352,27 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        //struct ist scheme = IST_NULL, authority = IST_NULL;
        struct ist authority = IST_NULL;
        int hdr_idx, ret;
-       int cookie = -1, last_cookie = -1;
+       int cookie = -1, last_cookie = -1, i;
+
+       /* RFC 9114 4.1.2. Malformed Requests and Responses
+        *
+        * A malformed request or response is one that is an otherwise valid
+        * sequence of frames but is invalid due to:
+        * - the presence of prohibited fields or pseudo-header fields,
+        * - the absence of mandatory pseudo-header fields,
+        * - invalid values for pseudo-header fields,
+        * - pseudo-header fields after fields,
+        * - an invalid sequence of HTTP messages,
+        * - the inclusion of uppercase field names, or
+        * - the inclusion of invalid characters in field names or values.
+        *
+        * [...]
+        *
+        * Intermediaries that process HTTP requests or responses (i.e., any
+        * intermediary not acting as a tunnel) MUST NOT forward a malformed
+        * request or response. Malformed requests or responses that are
+        * detected MUST be treated as a stream error of type H3_MESSAGE_ERROR.
+        */
 
        TRACE_ENTER(H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
 
@@ -416,6 +436,14 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                if (isteq(list[hdr_idx].n, ist("")))
                        break;
 
+               for (i = 0; i < list[hdr_idx].n.len; ++i) {
+                       const char c = list[hdr_idx].n.ptr[i];
+                       if ((uint8_t)(c - 'A') < 'Z' - 'A' || !HTTP_IS_TOKEN(c)) {
+                               TRACE_ERROR("invalid characters in field name", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
+                               return -1;
+                       }
+               }
+
                if (isteq(list[hdr_idx].n, ist("cookie"))) {
                        http_cookie_register(list, hdr_idx, &cookie, &last_cookie);
                        continue;

Репозитории - haproxy-2.7.git/commit

Ниже представлен код, демонстрирующий отсутствие санитизации имён заголовков в реализации обработки стандартных заголовков в HAProxy 2.7.0.

root@kitploit:~
/* 
src/h3.c 
строки: 413 - 428
*/

/* теперь обрабатываем стандартные заголовки */
hdr_idx = 0;
while (1) {
    if (isteq(list[hdr_idx].n, ist("")))
        break;
    if (isteq(list[hdr_idx].n, ist("cookie"))) {
        http_cookie_register(list, hdr_idx, & cookie, & last_cookie);
        continue;
    }
    if (!istmatch(list[hdr_idx].n, ist(":")))
        htx_add_header(htx, list[hdr_idx].n, list[hdr_idx].v);
    ++hdr_idx;
}

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

Код начинается с цикла for, который проходит по каждому символу имени поля заголовка. Цикл выполняется от i = 0 до i < list[hdr_idx0.n.len], где list — массив или структура, содержащая информацию о заголовках, а hdr_idx — индекс, указывающий на конкретный проверяемый заголовок.
Внутри цикла код извлекает текущий символ c из имени поля заголовка. list[hdr_idx].n.ptr[i] обращается к символу на позиции i в имени поля заголовка. Следующая часть кода содержит оператор if. Он проверяет, удовлетворяет ли текущий символ c одному из двух условий:

  • (uint8_t)(c - 'A') < 'Z' - 'A': Это проверяет, является ли символ заглавной буквой (от A до Z), вычитая 'A' из c и приводя результат к uint8_t. Если результат меньше разницы между 'Z' и 'A', значит символ — заглавная буква.
  • !HTTP_IS_TOKEN(c): Это условие проверяет, является ли символ допустимым токеном HTTP. HTTP_IS_TOKEN работает, сначала проверяя, содержит ли имя заголовка какие-либо токены. Токен — это последовательность символов, не являющихся зарезервированными символами в протоколе HTTP. Зарезервированные символы — это символы, имеющие специальное значение в протоколе HTTP, например, :, /, ? и #.
root@kitploit:~
/* 
src/h3.c 
строки: 439 - 445
*/
for (i = 0; i < list[hdr_idx].n.len; ++i) {
    const char c = list[hdr_idx].n.ptr[i];
    if ((uint8_t)(c - 'A') < 'Z' - 'A' || !HTTP_IS_TOKEN(c)) {
        TRACE_ERROR("invalid characters in field name", H3_EV_RX_FRAME | H3_EV_RX_HDR, qcs -> qcc -> conn, qcs);
        return -1;
    }
}

Настройка лаборатории

Вся лаборатория работает на Docker. Вы можете запустить её с помощью следующих команд:

  1. cd /lab
  2. docker-compose up --build

Обратите внимание, что сборка Docker займёт 15-20 минут.
Однако перед запуском лаборатории необходимо внести некоторые изменения в конфигурацию:

/lab/haproxy/conf/haproxy.cfg

root@kitploit:~
...
default_backend api_server

backend api_server
  balance roundrobin
  server api_server [YOUR-LOCAL-IPv4]:8080 # замените на локальный IPv4

/etc/hosts

root@kitploit:~
[YOUR-LOCAL-IPv4]   foo.com

/lab/docker-compose.yml
Вы можете выбрать между уязвимой и исправленной версией, изменив значение аргумента на 'vuln' или 'patched' для проведения теста.

root@kitploit:~
...
    args:
        - haproxy_version=patched || vuln
...

и, наконец, импортируйте сертификат minica.crt в свой браузер.

⚠️ Пожалуйста, запускайте лабораторию в среде Linux.

Выявление проблемы

Отправка следующего curl-запроса:

  • curl --http3 -H "foooooo\r\n: barr" -iL -k https://192.168.1.104/

Ответ уязвимой версии:

root@kitploit:~
HTTP/3 200 
server: Werkzeug/2.3.6 Python/3.8.17  
date: Sat, 12 Aug 2023 13:10:52 GMT   
content-type: text/html; charset=utf-8
content-length: 76
alt-svc: h3=":443";ma=900;

Host: 192.168.1.104
User-Agent: curl/8.1.2-DEV
Accept: */*
Foooooo\R\N: barr <-- Некорректный заголовок

Ответ исправленной версии:

root@kitploit:~
curl: (56) HTTP/3 stream 0 reset by server

На основе приведённых выше результатов соответствующие ответы показывают, что уязвимая версия HAProxy пропустила префикс \r\n к внутреннему серверу, тогда как исправленная версия разорвала соединение между клиентом и HAProxy.


Злоумышленник может провести атаку по подмене HTTP-запроса (HTTP Request Smuggling) в зависимости от поведения внутреннего сервера и того, как он обрабатывает некорректный заголовок. На мой взгляд, наибольшую опасность представляет то, что злоумышленник может использовать вышеупомянутую CVE для проведения атаки типа «отказ в обслуживании» (DoS).

Ссылки:

https://jvn.jp/en/jp/JVN38170084/
https://github.com/haproxytechblog/haproxy-2.6-http3
https://www.haproxy.com/blog/how-to-enable-quic-load-balancing-on-haproxy
https://git.haproxy.org/
https://github.com/jsha/minica
https://curl.se/docs/http3.html

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