Блог

CVE-2026-45185 Dead.Letter: один байт в освобождённую память — и ваш почтовый сервер чужой

CVE-2026-45185-DeadLetter-Exim
CVE / Безопасность

CVE-2026-45185 Dead.Letter: один байт в освобождённую память — и ваш почтовый сервер чужой

Exim принял TLS-соединение. Клиент начал передавать тело письма через BDAT, потом внезапно прислал TLS close_notify — сигнал завершения сессии — в середине передачи. Exim освободил буфер. Но вложенный обработчик BDAT продолжил читать байты и вызвал ungetc(), записав один символ \n в уже освобождённую память. Один байт. На метаданные аллокатора. Этого достаточно для RCE без аутентификации.

CVE-2026-45185, получившая имя Dead.Letter — use-after-free в парсере BDAT Exim при использовании GnuTLS. CVSS 9.8, CWE-416 (Use After Free). Затронуты версии 4.97–4.99.2, собранные с параметром USE_GNUTLS=yes. Патч вышел 12 мая 2026 года в версии 4.99.3. PoC опубликован, данных об активной эксплуатации на момент выхода патча не было — но с тех пор прошло три недели.

Уязвимость нашёл исследователь Federico Kirschbaum из XBOW Security, который, по его собственным словам, никогда прежде не читал исходный код Exim. Именно это делает историю интересной: баг прятался на виду девять лет.

ЧТО ТАКОЕ EXIM И BDAT

Exim — один из самых распространённых Mail Transfer Agent на Unix-системах. Debian, Ubuntu и их производные исторически поставляют Exim в качестве MTA по умолчанию, и большинство таких сборок используют GnuTLS как TLS-библиотеку. Это значит, что миллионы почтовых серверов по всему миру потенциально затронуты — просто потому что они стоят на Debian-based дистрибутиве.

BDAT — это расширение SMTP под названием CHUNKING (RFC 3030). Вместо традиционной команды DATA, которая завершает тело письма точкой на отдельной строке, BDAT позволяет клиенту передавать тело чанками с явным указанием размера: BDAT 1234, BDAT 5678 LAST. Это эффективнее для больших писем и стандартно поддерживается в современных Exim-версиях — никакой специальной конфигурации не требуется.

Важно понимать структуру: когда Exim работает поверх TLS, у него есть два уровня — TLS-сессия (управляет шифрованием через GnuTLS) и SMTP-уровень (разбирает команды и тело письма). Проблема возникает на стыке этих двух уровней, когда TLS завершается раньше, чем SMTP-обработчик успевает закончить свою работу.

КАК РАБОТАЕТ ОШИБКА

После успешного TLS-хендшейка Exim аллоцирует буфер передачи через store_malloc() и подменяет стандартные SMTP-функции приёма на TLS-обёртки. Этот буфер (xfer_buffer) живёт внутри состояния GnuTLS-сессии и освобождается при закрытии TLS-соединения.

Уязвимая последовательность выглядит так: клиент устанавливает TLS-соединение, отправляет команду BDAT и начинает передачу тела письма. В середине передачи — до отправки финального чанка с флагом LAST — клиент посылает TLS close_notify. GnuTLS получает сигнал завершения сессии и освобождает все связанные ресурсы, включая xfer_buffer. Но вложенный обработчик BDAT не знает об этом: он продолжает ждать финальный байт и вызывает ungetc('\n', ...), записывая символ перевода строки в уже освобождённый регион памяти.

Этот единственный байт приземляется на метаданные аллокатора Exim — структуры, которые описывают, какие блоки памяти свободны, какие заняты, каков их размер. Запись в метаданные аллокатора — это не просто порча памяти, это возможность контролировать поведение следующих вызовов malloc() и free(). Именно это открывает путь к дальнейшей эксплуатации.

КАК ЭТО ЭКСПЛУАТИРУЕТСЯ

Запись одного байта в метаданные аллокатора — примитив слабый, но достаточный. Как пишет Kirschbaum в своём writeup, на базе этой записи строятся более сильные примитивы: контролируемые записи по произвольным адресам, что в итоге позволяет перезаписать указатель на функцию внутри процесса Exim.

Для запуска атаки нужно только установить TLS-соединение и поддерживать BDAT — оба условия выполняются в стандартной конфигурации любого современного Exim с GnuTLS. Никакой аутентификации, никаких учётных данных, никаких предварительных знаний о сервере. Единственное требование — чтобы Exim был собран с GnuTLS, что является дефолтом для Debian и Ubuntu.

XBOW во время окна ответственного раскрытия проверили, насколько далеко можно продвинуться в разработке эксплойта — как вручную, так и с помощью автономных инструментов. Результаты они описывают как достаточно убедительные, чтобы уверенно классифицировать уязвимость как практически эксплуатируемую RCE, а не теоретическую heap corruption.

ЧТО ПРОИСХОДИТ ДАЛЬШЕ — ЗАВИСИТ ОТ КОНФИГУРАЦИИ

Exim обычно запускается от непривилегированного пользователя Debian-exim или аналогичного. Если systemd-юнит сервиса не настроен с PrivateTmp, NoNewPrivileges и ограничением capabilities — атакующий получает shell с правами этого пользователя. Дальнейшее повышение привилегий зависит от конфигурации системы.

Однако на многих серверах Exim запускается с правами root для отдельных операций — например, для доставки почты локальным пользователям через setuid-биты. Если на сервере не настроена изоляция процессов через systemd или не используются Linux namespaces, компрометация Exim может напрямую дать root. Проверьте под каким пользователем реально работает процесс:

ps aux | grep exim

Первая колонка — пользователь. Если там root — при успешной эксплуатации атакующий сразу получает root-доступ. Если Debian-exim или аналогичный непривилегированный пользователь — ущерб ограничен правами этого процесса, но RCE всё равно состоялся.

Если же сервер использует Exim только как relay и не принимает почту от произвольных внешних клиентов — фактический риск ниже. Но если порты 25, 465 или 587 открыты для интернета и версия Exim уязвима — это прямая атаковая поверхность без каких-либо барьеров.

РЕАЛЬНАЯ ЦЕПОЧКА АТАКИ

Атакующий начинает с разведки: сканирует порт 25, получает SMTP-баннер с версией Exim, делает EHLO и смотрит на список расширений. Если сервер отвечает 250-CHUNKING — BDAT поддерживается. Если в баннере или через другие fingerprinting-методы удаётся подтвердить версию из диапазона 4.97–4.99.2 — сервер в зоне поражения. Всё это занимает секунды и не требует ни учётных данных, ни специальных инструментов.

Дальше — установить TLS-соединение и воспроизвести уязвимую последовательность: отправить BDAT, начать передачу тела, в середине прислать TLS close_notify, затем финальный байт в открытом виде. Exim пишет \n в освобождённую память. Сервер либо падает с сигналом, что подтверждает уязвимость, либо — при правильно подготовленной heap-раскладке — продолжает работать с повреждёнными метаданными аллокатора, что открывает путь к дальнейшей эксплуатации.

Именно эту часть — от heap corruption до полноценного RCE — XBOW исследовали в период ответственного раскрытия. Путь длинный: нужно понять поведение аллокатора Exim при конкретных паттернах аллокации, выстроить более сильные примитивы из слабой однобайтовой записи, найти способ перезаписать указатель на функцию. Kirschbaum публично описал это как реализуемое — и XBOW проверили это как руками, так и автономными инструментами. Публичного готового эксплойта до shell на момент раскрытия не было, но это вопрос времени и мотивации атакующего.

ТАЙМЛАЙН

1 мая 2026 года Federico Kirschbaum из XBOW Security отправил первый отчёт команде Exim. Это был результат работы их инструмента автономного поиска уязвимостей — примечательно, что сам Kirschbaum никогда прежде не работал с кодовой базой Exim.

4 мая Kirschbaum отправил follow-up с запросом статуса. 5 мая мейнтейнеры Exim подтвердили уязвимость и сообщили, что приватный патч уже в работе. 7 мая началась координация раскрытия с мейнтейнерами дистрибутивов.

12 мая 2026 года опубликована CVE-2026-45185 и одновременно выпущен Exim 4.99.3 с исправлением. В тот же день XBOW опубликовали свой writeup Dead.Letter с техническими деталями уязвимости. Публичный скрипт детекции появился на GitHub вскоре после раскрытия.

Стоит отметить скорость: от первого отчёта 1 мая до публичного патча 12 мая — 11 дней. Для open source проекта с небольшой командой мейнтейнеров это быстро. Такая скорость стала возможной потому что XBOW изначально предоставили детальный отчёт с точным описанием механизма, что позволило команде Exim сразу приступить к исправлению, не тратя время на воспроизведение.

ПОЧЕМУ ЭТО ВАЖНО

Exim — не нишевое ПО. По данным различных сканирований, он обрабатывает значительную долю интернет-почты, и большинство установок на Debian/Ubuntu используют именно GnuTLS. Почтовые серверы по определению открыты интернету и принимают соединения от любых клиентов — у атакующего нет никаких препятствий для попытки эксплуатации, кроме версии Exim и TLS-библиотеки.

Особенно неприятен масштаб потенциально уязвимых систем: многие хостинг-провайдеры и VPS-операторы поставляют образы с Exim из коробки. Системные администраторы, которые никогда специально не занимались настройкой MTA, могут не знать, что на их сервере вообще работает Exim — и тем более не знать, с какой TLS-библиотекой он собран.

Наконец, история с тем, что баг похожего класса — use-after-free в BDAT — уже существовал в Exim в 2017 году (CVE-2017-16943, тоже CVSS 9.8), говорит о системной сложности этого компонента. Одна и та же область кода дважды за девять лет порождает критическую уязвимость. Это не случайность и не невнимательность конкретного разработчика — это признак того, что граница между TLS-слоем и SMTP-обработчиком в Exim структурно сложна и плохо поддаётся проверке. Хорошей новостью является то, что XBOW нашли этот баг инструментально, не разбираясь в кодовой базе месяцами. Плохой — что те же инструменты доступны и атакующим.

ОБНОВЛЕНИЕ

Официальный advisory Exim однозначен: никакого митигации нет, единственное решение — обновление до 4.99.3. Никаких конфигурационных флагов, никакого «отключить CHUNKING и подождать» — только патч.

Первым делом — проверить версию Exim и TLS-библиотеку. Команда exim -bV выводит детали сборки — версию, дату компиляции и список поддерживаемых возможностей, среди которых будет указана TLS-библиотека:

exim -bV | grep -E "version|TLS"

Ищите в выводе строку с версией и строку со списком поддержки. Если там GnuTLS и версия ниже 4.99.3 — сервер уязвим и нужно обновляться немедленно. Если вместо GnuTLS стоит OpenSSL — эта сборка уязвимостью не затронута.

На Debian/Ubuntu обновить через apt. Сначала убедитесь, что репозиторий уже содержит исправленную версию:

apt-cache policy exim4

Смотрите строку Candidate:. Если там версия с 4.99.3 или новее — обновляйте:

apt update && apt install exim4

Если репозиторий ещё не обновился — скачайте напрямую с официального FTP Exim. Оба адреса указаны в официальном advisory: ftp.exim.org/pub/exim/exim4/ и code.exim.org/exim/exim/releases. Скачать и распаковать:

wget https://ftp.exim.org/pub/exim/exim4/exim-4.99.3.tar.xz
tar xf exim-4.99.3.tar.xz

Сборка из исходников требует наличия зависимостей и конфигурационного файла Local/Makefile — для большинства продакшн-серверов проще дождаться обновления пакета в репозитории, чем собирать вручную. Если ждать нельзя — собирайте с теми же параметрами, что и текущая установка (их видно в выводе exim -bV). После обновления проверьте версию повторно:

exim -bV | grep version

Вывод должен показать 4.99.3. Для быстрой проверки большого числа серверов есть скрипт детекции от liamromanis101 на GitHub (Dead.Letter-CVE-2026-45185) — он проверяет версию, TLS-бэкенд и конфигурацию. Требует прав на чтение конфига Exim, запускать от root или пользователя группы Debian-exim.

ВЫВОДЫ

Dead.Letter — один байт в освобождённую память, CVSS 9.8, уязвимость в компоненте который принимает соединения от всего интернета без аутентификации. Официальный advisory Exim не оставляет вариантов: митигации нет, только обновление до 4.99.3.

Проверьте прямо сейчас: exim -bV | grep -E "version|TLS". Если видите GnuTLS и версию ниже 4.99.3 — обновляйтесь. Если репозиторий ещё не обновился — скачивайте напрямую с ftp.exim.org. Это не задача на следующий спринт.

Leave your thought here

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поддержать автора

Если вам понравилась статья — вы можете поддержать автора.

Crypto donation button by NOWPayments