Сканер уязвимостей на основе shell для CVE-2026-45185 (Dead.Letter) в Exim MTA. Обнаруживает use-after-free в сборках GnuTLS, проверяет версию, библиотеку TLS и конфигурацию CHUNKING. Создает JSON-вывод для интеграции CI/CD.
Скрипт оболочки для обнаружения уязвимости CVE-2026-45185 в Linux-системах — это использование после освобождения (use-after-free) в агенте передачи почты Exim, что может привести к удалённому выполнению кода.
Предназначен для использования в CI/CD-конвейерах, инструментах управления конфигурацией и разовых аудитах системы. Выдаёт как человекопонятный, так и машинопонятный (JSON) вывод.
CVE-2026-45185 (псевдоним: Dead.Letter) — это ошибка использования после освобождения в разборе тела сообщения в формате BDAT (двоичные данные) Exim, которая срабатывает при обработке TLS через GnuTLS.
Во время завершения сеанса TLS Exim освобождает свой буфер передачи TLS, но вложенная обёртка приёма BDAT всё ещё может обрабатывать входящие байты и вызывать ungetc(), записывая один байт \n в освобождённую область. Эта однобайтовая запись повреждает метаданные распределителя кучи, что позволяет атакующему получить дальнейшие примитивы работы с памятью и добиться удалённого выполнения кода.
| Свойство | Подробности |
|---|
| CVE | CVE-2026-45185 |
| Псевдоним | Dead.Letter |
| Тип | Использование после освобождения (CWE-416) |
| Компонент | Обработчик BDAT/CHUNKING Exim (только сборки с GnuTLS) |
| Вектор атаки | Сеть — без аутентификации, требуется только TLS-соединение и расширение CHUNKING |
| Затрагиваемые версии | Exim 4.97 – 4.99.2, только сборки с GnuTLS |
| Исправлено в | Exim 4.99.3 |
| Обнаружено | Federico Kirschbaum, XBOW Security Lab (сообщено 1 мая 2026) |
Сборки с OpenSSL не затрагиваются. Уязвимость специфична для Exim, скомпилированного с
USE_GNUTLS=yes. Если ваш Exim использует OpenSSL, вы не уязвимы независимо от версии.
Скрипт работает по дереву решений, останавливаясь и помечая систему не уязвимой, как только подтверждено определённое безопасное состояние:
Проверка 1 — наличие Exim
Ищет в $PATH и стандартных местах установки (/usr/sbin/exim, /usr/sbin/exim4, /usr/local/sbin/exim). Если Exim не найден, система не уязвима, и скрипт немедленно завершает работу.
Проверка 2 — версия Exim
Разбирает вывод exim -bV и сравнивает с уязвимым диапазоном (4.97 – 4.99.2). Версии ≥ 4.99.3 считаются исправленными. Версии вне известного диапазона помечаются как не уязвимые (с пометкой, если они не распознаны).
Проверка 3 — библиотека TLS (критический шлюз) Использует три метода обнаружения последовательно:
exim -bV (наиболее надёжная — Exim сообщает свои возможности времени компиляции, например Support for: GnuTLS)lddstrings (запасной вариант)Если обнаружен OpenSSL → вердикт меняется на не уязвим независимо от версии. Если обнаружен GnuTLS → подтверждена поверхность атаки. Если ни то, ни другое не удаётся определить → результат неопределённый.
Проверка 4 — конфигурация CHUNKING/BDAT (проверка обходного решения)
Запускается только если система всё ещё помечена как уязвимая. Проверяет, установлено ли chunking_advertise_hosts явно в пустое значение в конфиге Exim, что отключает объявление BDAT и блокирует вектор атаки. Обрабатывает как однофайловые конфиги, так и раздельную конфигурацию Debian (фрагменты /etc/exim4/conf.d/).
Примечание: если
chunking_advertise_hostsотсутствует в конфиге (по умолчанию), Exim объявляет CHUNKING всем хостам (*). Чтобы отключить, параметр должен быть явно установлен в пустое значение.
Проверка 5 — информационные смягчения системы Не меняет вердикт, но сообщает о факторах, влияющих на эксплуатацию:
/proc/sys/kernel/randomize_va_space) — должен быть 2checksec для бинарного файла Exim (PIE, RELRO, канарейки стека), если установлен checksecMemoryDenyWriteExecute, NoNewPrivileges, SystemCallFilter/proc (для проверки ASLR)grep, awk, ldd, headchecksec (опционально — для анализа защиты бинарного файла)systemctl (опционально — для проверки юнита systemd)Debian-exim на Debian/Ubuntu)Для основных проверок уязвимости внешние зависимости не требуются.
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh
| Флаг | Описание |
|---|---|
--json | Вывод результатов в виде объекта JSON (см. ниже) |
--quiet | Подавить весь вывод; устанавливается только код возврата |
--no-color | Отключить ANSI-цвета (полезно для логов) |
--help / -h | Вывести информацию об использовании |
| Код | Значение |
|---|---|
0 | Не уязвим (или найдено определённое безопасное состояние) |
1 | Уязвим |
2 | Неопределённо — не удалось определить один или более требуемых фактов; считайте потенциально уязвимым |
3 | Ошибка скрипта или неподдерживаемая среда |
CVE-2026-45185 (Dead.Letter) — Exim Vulnerability Assessment
============================================================
[CHECK] Checking for Exim installation...
[WARN] Exim binary found: /usr/sbin/exim4
[CHECK] Checking Exim version...
Detected version: 4.99.1
[FAIL] Exim 4.99.1 is in the vulnerable range (4.97 – 4.99.2).
[CHECK] Checking TLS library linkage (GnuTLS vs OpenSSL)...
[FAIL] Exim is linked against GnuTLS — this build IS affected.
[CHECK] Checking CHUNKING (BDAT) advertisement config...
Config file: /etc/exim4/exim4.conf
[WARN] chunking_advertise_hosts is not disabled — BDAT is active (default advertises to all hosts).
Tip: add 'chunking_advertise_hosts =' (empty value) to your main config to disable BDAT as a workaround.
[CHECK] Checking system-level exploit mitigations (informational)...
[PASS] ASLR: full randomisation (randomize_va_space=2)
glibc version: 2.35 (2.32+ has stronger heap metadata checks)
[WARN] systemd: MemoryDenyWriteExecute not set — recommend adding to unit
[WARN] systemd: NoNewPrivileges not set
------------------------------------------------------------
VERDICT
------------------------------------------------------------
VULNERABLE — CVE-2026-45185
Reason: Exim version 4.99.1 is in vulnerable range 4.97–4.99.2
Recommended actions:
1. Upgrade Exim to 4.99.3 or later (primary fix)
2. As a workaround, set 'chunking_advertise_hosts =' (empty) in exim config
3. Add MemoryDenyWriteExecute=yes and NoNewPrivileges=yes to the systemd unit
4. Ensure ASLR is set to 2: echo 2 > /proc/sys/kernel/randomize_va_space
------------------------------------------------------------
--json){
"cve": "CVE-2026-45185",
"alias": "Dead.Letter",
"host": "mailserver-01",
"timestamp": "2026-05-12T17:00:00Z",
"verdict": "vulnerable",
"reason": "Exim version 4.99.1 is in vulnerable range 4.97–4.99.2",
"exit_code": 1,
"findings": {
"exim_binary": "/usr/sbin/exim4",
"exim_version": "4.99.1",
"exim_version_vulnerable": "true",
"tls_library": "gnutls",
"tls_library_detected": "gnutls",
"exim_config": "/etc/exim4/exim4.conf",
"chunking_advertised": "true",
"aslr_level": "2",
"glibc_version": "2.35"
},
"mitigations": [
"aslr=full"
]
}
- name: Check for CVE-2026-45185
run: |
chmod +x check_cve_2026_45185.sh
./check_cve_2026_45185.sh --json | tee vuln-report.json
exit $(jq '.exit_code' vuln-report.json)
- name: Upload vulnerability report
if: always()
uses: actions/upload-artifact@v4
with:
name: cve-2026-45185-report
path: vuln-report.json
check-exim-vuln:
stage: security
script:
- chmod +x check_cve_2026_45185.sh
- ./check_cve_2026_45185.sh --json > vuln-report.json
artifacts:
when: always
paths:
- vuln-report.json
allow_failure: false
- name: Run CVE-2026-45185 check
script: check_cve_2026_45185.sh --json
register: vuln_check
failed_when: vuln_check.rc == 1
changed_when: false
- name: Show vulnerability report
debug:
msg: "{{ vuln_check.stdout | from_json }}"
# Get just the verdict
./check_cve_2026_45185.sh --json | jq -r '.verdict'
# Check if a specific mitigation was found
./check_cve_2026_45185.sh --json | jq '.mitigations | contains(["aslr=full"])'
# Run across multiple hosts and collect results
for host in mail1 mail2 mail3; do
ssh "$host" 'bash -s' < check_cve_2026_45185.sh --json
done | jq -s '.'
# Debian / Ubuntu
apt-get update && apt-get install --only-upgrade exim4
# RHEL / CentOS / Fedora
dnf upgrade exim
# From source
# Download 4.99.3 from https://ftp.exim.org/pub/exim/exim4/
# and rebuild with your existing Local/Makefile settings
Проверьте после обновления:
exim -bV | head -1
# Expected: Exim version 4.99.3 ...
Если вы не можете немедленно обновить, добавление следующей строки в основной раздел конфигурации вашего конфига Exim полностью отключает объявление BDAT, блокируя вектор атаки:
chunking_advertise_hosts =
Пустое значение означает «нет хостов» — Exim больше не будет объявлять расширение CHUNKING в ответах EHLO. После изменения перезапустите Exim:
# Debian / Ubuntu
systemctl restart exim4
# Other systemd systems
systemctl restart exim
Проверьте, что CHUNKING больше не объявляется:
# Connect and check the EHLO response — CHUNKING should not appear
echo QUIT | openssl s_client -connect localhost:25 -starttls smtp 2>/dev/null \
| grep -i chunking
# No output = CHUNKING is disabled
Это обходное решение, а не исправление. Некоторые отправляющие почтовые серверы используют BDAT для доставки больших сообщений. Его отключение может вызвать проблемы совместимости с такими отправителями. Обновитесь до 4.99.3 как можно скорее.
Даже на исправленной системе добавление этих директив в юнит systemd Exim снижает влияние любой будущей уязвимости повреждения памяти:
# /etc/systemd/system/exim4.service.d/hardening.conf
[Service]
NoNewPrivileges=yes
MemoryDenyWriteExecute=yes
ProtectSystem=strict
PrivateTmp=yes
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallFilter=@system-service
systemctl daemon-reload && systemctl restart exim4
ldd и strings, которые могут быть менее надёжными.