Статья Preauth RCE и обход mTLS: разбор уязвимостей Mongoose на миллионах устройств

1780401353038.webp

Комментарий в продакшн-коде «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 атакующий выдаёт себя за легитимный клиент и получает доступ к управляющим интерфейсам
По данным Mandiant M-Trends 2025, эксплойты - наиболее распространённый вектор initial access: 38% всех инцидентов. IBM X-Force фиксирует, что 70% отслеживаемых атак в 2024 году затронули критическую инфраструктуру - тот самый сегмент, где Mongoose живёт.

Сводка CVE​

CVEТипCVSS 4.0CWEАвтоматизируема (CISA)PoC
CVE-2026-5244Heap overflow (TLS cert)5.5 MEDIUMCWE-119, CWE-122ДаПубличный
CVE-2026-5245Stack overflow (mDNS)2.9 LOWCWE-119, CWE-121НетПубличный
CVE-2026-5246mTLS bypass (P-384)2.9 LOWCWE-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 - аутентификация без верификации​

1780403084453.webp

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: отсутствует
RSA-ключ размером 8192 бит - модуль ~1037 байт. Это 509 байт за пределами 528-байтного буфера. Overflow перезаписывает смежные аллокации в куче.

На 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Прямой shellcodeInfo 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). Рекомендации по приоритету:
  1. Обновление до v7.21 - основной путь. Для устройств с OTA - приоритет критический.
  2. Замена TLS-стека - переключение с MG_TLS_BUILTIN на OpenSSL или mbedTLS устраняет CVE-2026-5244 и CVE-2026-5246. Требует перекомпиляции прошивки, но убирает хронически проблемный компонент.
  3. Отключение mDNS - если не используется, деактивация закрывает CVE-2026-5245.
  4. Отказ от P-384 CA - временная мера: переход на P-256 устраняет CVE-2026-5246 без обновления библиотеки. Да, теряем 64 бита security level - но лучше рабочая P-256 верификация, чем нерабочая P-384.
  5. Сетевая сегментация - для непатчируемых устройств (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 займут минуту. Результат может неприятно удивить.
 
Последнее редактирование модератором:
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab