Комментарий в продакшн-коде «ignore secp386 for now» - и P-384 mTLS превращается в декорацию. Heap overflow в TLS-хендшейке - preauth RCE как root ещё до первого HTTP-запроса. Stack overflow через mDNS - один UDP-пакет. Всё это - Mongoose, embedded C-библиотека, которая, по заявлению Cesanta, крутится на сотнях миллионов устройств Siemens, Schneider Electric, Google, Samsung и Qualcomm. Второго апреля 2026 года Simone Margaritelli (evilsocket) выложил дисклоуз трёх CVE, затрагивающих версии 7.0–7.20. Патч - в 7.21. Разберём, что сломано и почему на типичном IoT-шлюзе это страшнее, чем выглядит по CVSS.
Дисклоуз - обнародование, раскрытие
Mongoose в цепочке атаки на embedded-инфраструктуру
Mongoose - однофайловая C-библиотека: HTTP/HTTPS, WebSocket, MQTT, mDNS для встраиваемых систем. Главная фишка - встроенная реализация TLS 1.3 (MG_TLS_BUILTIN), чтобы не тащить за собой OpenSSL или mbedTLS на устройства, где каждый килобайт прошивки на счету. Целевые платформы: MIPS и ARM SoC, FreeRTOS, Zephyr, bare-metal контроллеры.На практике Mongoose встречается в IP-камерах, SCADA-шлюзах, системах управления зданиями, медицинских устройствах и автомобильных информационно-развлекательных системах. Cesanta утверждает, что библиотека работает даже на МКС. Список заявленных пользователей - промышленные гиганты, но большинство конечных операторов понятия не имеют, какой TLS-стек крутится внутри купленного контроллера.
Три CVE покрывают несколько тактик по MITRE ATT&CK:
- Initial Access - Exploit Public-Facing Application (T1190): все три эксплуатируются удалённо, без аутентификации, против сетевых сервисов
- Privilege Escalation - Exploitation for Privilege Escalation (T1068): heap overflow в CVE-2026-5244 даёт выполнение кода с правами процесса Mongoose - на embedded это root
- Defense Impairment - Weaken Encryption (T1600): обход mTLS через CVE-2026-5246 полностью убивает взаимную аутентификацию
- Credential Access - Adversary-in-the-Middle (T1557): после обхода mTLS атакующий выдаёт себя за легитимный клиент и получает доступ к управляющим интерфейсам
Сводка CVE
| CVE | Тип | CVSS 4.0 | CWE | Автоматизируема (CISA) | PoC |
|---|---|---|---|---|---|
| CVE-2026-5244 | Heap overflow (TLS cert) | 5.5 MEDIUM | CWE-119, CWE-122 | Да | Публичный |
| CVE-2026-5245 | Stack overflow (mDNS) | 2.9 LOW | CWE-119, CWE-121 | Нет | Публичный |
| CVE-2026-5246 | mTLS bypass (P-384) | 2.9 LOW | CWE-285, CWE-639 | Нет | Публичный |
CVSS 4.0 даёт формально невысокие оценки - параметр AC:H (высокая сложность) для CVE-2026-5245 и CVE-2026-5246, «partial» impact по всем трём. Но формальный score не учитывает реальность embedded: отсутствие ASLR и исполняемая куча превращают «medium» в root shell за один хендшейк. Я бы смотрел не на CVSS, а на конфигурацию конкретного устройства.
CVE-2026-5246: mTLS bypass через P-384 - аутентификация без верификации
Mutual TLS - стандарт device-to-device аутентификации в IoT. Обе стороны предъявляют X.509-сертификаты, подписанные доверенным CA. Сервер проверяет подпись клиентского сертификата, и только при валидной цепочке доверия клиент получает доступ. Так должно работать.
В Mongoose за верификацию отвечает
mg_tls_verify_cert_signature() в tls_builtin.c. Проблема - в обработке кривой P-384 (secp384r1): когда CA-сертификат использует P-384 ECDSA-ключ, функция возвращает 1 (success) без выполнения какой-либо проверки подписи. Вообще. По данным исследователя, комментарий в коде: «ignore secp386 for now»«Теперь игнорируется secp386». Даже название кривой с опечаткой - secp386 вместо secp384.NVD присвоил CVE-2026-5246 оценку CVSS 4.0 2.9 (LOW) с вектором AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L. CWE: CWE-285 (Improper Authorization) и CWE-639 (Authorization Bypass Through User-Controlled Key). CISA в рамках SSVC - Track* (следить, готовить патч), пометка exploitation: poc.
Что это значит на практике? Если Mongoose-сервер с mTLS использует P-384 CA - а это разумный выбор, P-384 даёт 192-битную безопасность против 128-битной у P-256, - то любой клиентский сертификат принимается. Сертификат, слепленный за пять секунд с произвольным CA, пройдёт «верификацию». mTLS превращается из механизма защиты в красивую декорацию.
Предусловия и ограничения
Работает если: Mongoose v7.0–7.20 сMG_TLS_BUILTIN, CA-сертификат использует P-384 (secp384r1), mTLS включена. Применимо для внешнего и внутреннего пентеста OT/ICS-инфраструктуры.Не работает если: сервер использует P-256 CA (проверка подписи выполняется корректно), внешний TLS-стек (OpenSSL, mbedTLS) вместо встроенного, или Mongoose 7.21+.
На этапе recon определяем тип кривой CA: подключаемся с произвольным самоподписанным сертификатом через
openssl s_client -cert ... -key .... Если сервер не разрывает TLS-хендшейк - с высокой вероятностью перед нами P-384 bypass.CVE-2026-5244: preauth RCE через heap overflow в TLS-хендшейке
Самая опасная из трёх по последствиям. Heap overflow возникает вmg_tls_recv_cert() при обработке клиентского сертификата во время TLS-хендшейка - до проверки подписи и до обработки первого HTTP-запроса. Ещё раз: до.NVD: CVE-2026-5244, CVSS 4.0 - 5.5 (MEDIUM), вектор AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L. Сетевой вектор, низкая сложность, без привилегий, без взаимодействия пользователя. CWE: CWE-119 и CWE-122 (Heap-based Buffer Overflow), причём CWE-122 классифицирован MITRE с likelihood High.
CISA SSVC: Track, exploitation: none, но automatable: yes - атака автоматизируема в масштабе. И вот тут CVSS 5.5 начинает выглядеть неадекватно.
Механика уязвимости
При обработке клиентского сертификата публичный ключ копируется в фиксированный буферpubkey внутри структуры tls_data размером 528 байт. Длина ключа ci->pubkey.len берётся прямо из DER-представления X.509-сертификата - полностью контролируется атакующим. Проверки границ нет.
C:
// Концептуальное представление уязвимого кода
// tls_builtin.c - mg_tls_recv_cert()
memmove(tls->pubkey, cert_pubkey_data, ci->pubkey.len);
// pubkey = фиксированный буфер 528 байт
// ci->pubkey.len = из DER сертификата, контролируется атакующим
// bounds check: отсутствует
На embedded MIPS-устройствах, скомпилированных с
-z execstack (типичная конфигурация - без PIE, без canaries, без RELRO), overflow перезаписывает указатель на функцию mg_connection->fn. Прямое выполнение шелл-кода от root. На MIPS Linux ядро устанавливает [URL='https://www.kernel.org/doc/html/latest/userspace-api/ELF.html']READ_IMPLIES_EXEC[/URL] как побочный эффект PT_GNU_STACK RWE - исполняемой становится не только стек, но и куча.Контекст эксплуатации
Работает если: целевое устройство используетMG_TLS_BUILTIN и принимает входящие TLS-соединения. Embedded MIPS/ARM без ASLR, без PIE, с исполняемой кучей - стандартная конфигурация IoT. Применимо для внешнего пентеста при прямом сетевом доступе к устройству.Не работает если: цель скомпилирована с полным набором hardenings (ASLR + PIE + stack canaries + NX heap). На Linux x86_64 с glibc и полным RELRO эксплуатация значительно сложнее - нужен information leak для обхода ASLR и ROP-цепочка вместо прямого шелл-кода.
Не зависит от CVE-2026-5246: heap overflow срабатывает при парсинге сертификата до проверки подписи. Обход mTLS не нужен для триггера - достаточно любого TLS-соединения с crafted-сертификатом. Два бага - независимые пути эксплуатации.
CVE-2026-5245: stack overflow через mDNS - RCE одним UDP-пакетом
Третья уязвимость - в обработчике mDNS-записей,handle_mdns_record(). Четыре DNS-записи упаковываются в стековый буфер размером 282 байта без проверки границ. Один UDP-пакет переполняет стек на 386 байт, перезаписывая сохранённые регистры и адрес возврата.NVD: CVE-2026-5245, CVSS 4.0 - 2.9 (LOW), вектор AV:N/AC:H. CWE: CWE-119 и CWE-121 (Stack-based Buffer Overflow, likelihood по MITRE - High). CISA SSVC: Track, exploitation: none, automatable: no.
С точки зрения kill chain - самый быстрый вектор initial access: один UDP-пакет, без TCP-соединения, без TLS-хендшейка. Но практическая эксплуатация ограничена.
Работает если: mDNS включена, TXT-буфер сконфигурирован больше дефолтного размера, платформа - MIPS с исполняемым стеком. Применимо во внутреннем пентесте при нахождении в одном broadcast-домене с устройством.
Не работает если: mDNS отключена, стандартный размер TXT-буфера, платформа с NX-стеком. UDP-based - не пройдёт через NAT или файрвол при внешнем пентесте.
Практическая эксплуатация: цепочка, fingerprinting, ограничения
Требования к окружению
Для воспроизведения и тестирования:
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Embedded vs сервер: где preauth RCE уязвимость Mongoose реально эксплуатируема
| Характеристика | Embedded MIPS/ARM (IoT) | GNU/Linux x86_64 (сервер) |
|---|---|---|
| ASLR | Обычно отключена | Включена |
| PIE | Нет | Зависит от сборки |
| Stack canaries | Нет | Обычно есть |
| Исполняемая куча | Да (READ_IMPLIES_EXEC) | Нет (NX) |
| CVE-5244 exploit | Прямой shellcode | Info leak + ROP chain |
| Цикл патчинга | Месяцы или никогда | Часы или дни |
По данным IBM X-Force Threat Intelligence Index 2025, среднее время между публикацией CVE и устранением - 29 месяцев, и это для серверного ПО. Для embedded цифра значительно выше: обновление прошивки PLC или медицинского устройства может потребовать физического доступа, координации с вендором или ре-сертификации (FDA для медоборудования). Для значительной части инсталляционной базы патч не дойдёт до устройства никогда - оно проработает с этой уязвимостью до списания.
Remediation и паттерн уязвимостей в TLS-реализации Mongoose
Исправление и mitigation
Патчи для всех трёх CVE - в Mongoose v7.21 (1 апреля 2026). Рекомендации по приоритету:- Обновление до v7.21 - основной путь. Для устройств с OTA - приоритет критический.
- Замена TLS-стека - переключение с
MG_TLS_BUILTINна OpenSSL или mbedTLS устраняет CVE-2026-5244 и CVE-2026-5246. Требует перекомпиляции прошивки, но убирает хронически проблемный компонент. - Отключение mDNS - если не используется, деактивация закрывает CVE-2026-5245.
- Отказ от P-384 CA - временная мера: переход на P-256 устраняет CVE-2026-5246 без обновления библиотеки. Да, теряем 64 бита security level - но лучше рабочая P-256 верификация, чем нерабочая P-384.
- Сетевая сегментация - для непатчируемых устройств (legacy PLC, медоборудование) единственная реальная мера - изоляция с мониторингом аномальных TLS-хендшейков и oversized сертификатов.
Паттерн: TLS в Mongoose как хронически слабое звено
Три CVE 2026 года - не первый случай. В 2024 году Nozomi Networks Labs нашли 10 уязвимостей в TLS-реализации Mongoose v7.14. Среди них CVE-2024-42386 (CVSS 3.1 - 8.2 HIGH, CWE-823: Use of Out-of-range Pointer Offset) и CVE-2024-42384 (CVSS 3.1 - 7.5 HIGH, CWE-190: Integer Overflow). Обе позволяли уронить устройство crafted TLS-пакетом.По данным Nozomi Networks, встроенная TLS-реализация Mongoose не была интегрирована в pipeline фаззинг-тестирования, несмотря на подключение к Google OSS-Fuzz. TLS-стек разрабатывался и тестировался менее тщательно, чем остальные компоненты - при том что именно он обрабатывает недоверенный сетевой ввод от удалённых клиентов. Nozomi написали собственный harness для фаззинга TLS-хендшейка и за ограниченное время нашли 10 memory corruption. Evilsocket спустя два года нашёл ещё три - на обновлённой версии. Паттерн очевиден: от v7.14 до v7.20 TLS-реализация Mongoose систематически содержит memory corruption, и каждый раз уязвимости находят внешние исследователи, а не вендор.
Для пентестера вывод конкретный: при обнаружении Mongoose на целевом устройстве TLS-стек - приоритетная поверхность атаки. Если устройство использует
MG_TLS_BUILTIN на любой версии до 7.21, вероятность эксплуатируемой уязвимости высока. Я бы начинал именно с TLS - crafted сертификат и oversized ключ как первый шаг, ещё до сканирования портов.Три CVE в Mongoose - частный случай системной проблемы: lightweight TLS-реализации для embedded пишутся в условиях жёстких ресурсных ограничений и тестируются на порядок слабее, чем OpenSSL или BoringSSL. P-384 в Mongoose проигнорировали буквально - с комментарием «ignore for now». CVSS 4.0 оценивает CVE-2026-5244 как MEDIUM, CVE-2026-5246 как LOW, но на типичном IoT-шлюзе без ASLR и с исполняемой кучей «medium» - это preauth root shell, а «low» - полный обход mTLS, которая была единственным барьером доступа.
Но самый неприятный аспект этой истории - не сами баги, а supply chain. Большинство организаций, эксплуатирующих устройства с Mongoose внутри, не знают, что используют Mongoose. Купили контроллер от вендора, mTLS включили, галочку в compliance поставили. А за TLS отвечает single-file C-библиотека, где P-384 пропущена со словами «потом сделаем». Пока индустрия не начнёт требовать SBOM для прошивок с тем же уровнем строгости, что и для серверного ПО, «ignore for now» в коде будет не исключением, а нормой. И следующий дисклоуз снова затронет «сотни миллионов устройств» - потому что никто не знал, какой TLS-стек работает на их собственном оборудовании. Проверьте своё -
strings по прошивке и grep mongoose займут минуту. Результат может неприятно удивить.
Последнее редактирование модератором: