
POC_CVE-2026-45185 для nuclei-templates
Этот репозиторий не является общецелевым PoC-репозиторием эксплойтов. Это локальная
лаборатория проверки для воспроизведения и анализа поведения
шаблона CVE-2026-45185, предназначенного для включения в
projectdiscovery/nuclei-templates.
Шаблон nuclei-кода — это не просто детектор версии.
Он напрямую управляет STARTTLS, BDAT, TLS close_notify и следующим
байтом SMTP в открытом виде на том же TCP-соединении.
Эта последовательность совпадает в локальной уязвимой лаборатории Exim 4.99.2 GnuTLS и
не совпадает в исправленной лаборатории Exim 4.99.3 GnuTLS в тех же условиях.
Текущий сигнал проверки — это удалённый оракул SMTP-ответов, а не прямое
наблюдение самой записи UAF. Внутренне эта CVE представляет собой use-after-free,
при котором байты новой строки (\r/\n) могут быть записаны в освобождённый буфер
передачи GnuTLS после завершения TLS. На практике клиент не может реалистично
наблюдать эту запись в освобождённый буфер напрямую через SMTP-ответы. Поэтому
данный README и шаблон не заявляют о прямом доказательстве
записи UAF bdat_ungetc -> tls_ungetc или RCE. Вместо этого шаблон обнаруживает
разницу в восстановлении стека/состояния приёма, которая появляется во время потока срабатывания.
При трассировке механизма уязвимости я заметил, что после TLS
close_notify во время обработки STARTTLS + BDAT, устаревшие указатели функций tls_*
могут оставаться в нижнем слое стека приёма BDAT вместо того, чтобы быть
правильно восстановленными до указателей функций smtp_*. Это состояние становится видимым
в том, как сервер обрабатывает следующую SMTP-команду. После того как разделённый BDAT достигает
первого завершения, отправка NOOP в той же сессии заставляет уязвимую лабораторию Exim 4.99.2
GnuTLS возвращать 421 lost input connection, в то время как исправленная лаборатория Exim 4.99.3
GnuTLS обрабатывает её нормально с 250 OK. Это чёткое различие в ответах между уязвимой и исправленной
версиями используется как сопоставитель (matcher) для локального, авторизованного шаблона nuclei-кода.
Более подробное описание потока уязвимости см. в
CVE-2026-45185-Technical-Analysis.md.
| Цель | Версия | TLS-бэкенд | STARTTLS | CHUNKING | Порт | Ожидаемый результат nuclei |
|---|---|---|---|---|---|---|
| уязвимая | Exim 4.99.2 | GnuTLS | да | да | 127.0.0.1:2525 | совпадение |
| исправленная | Exim 4.99.3 | GnuTLS | да | да | 127.0.0.1:2526 | не совпадение |
Общий SMTP-получатель конверта (RCPT TO):
[email protected]
ACL lab_rcpt лаборатории Docker принимает этого получателя конверта. В общем
SMTP-целевом хосте, если RCPT TO отклонён, последовательность может не достичь парсера
тела BDAT, поэтому шаблону нужен принятый получатель.
Это значение отличается от заголовка To: внутри тела BDAT. Получатель
RCPT TO — это адрес SMTP-конверта, который должен пройти проверки получателя на сервере.
Значение To: в теле BDAT — это только текст заголовка сообщения; ему не обязательно
существовать или быть принятым как почтовый ящик сервером.
templates/CVE-2026-45185.yaml
Имя шаблона:
Exim 4.97-4.99.2 GnuTLS STARTTLS BDAT - Same-Session Response Check
Шаблон написан с metadata.verified: true и имеет теги code и
intrusive.
Выполните следующие команды из каталога POC_2026_45185/.
docker compose build
docker compose up -d
Проверьте синтаксис шаблона:
nuclei -duc -validate -code -t templates/CVE-2026-45185.yaml
Подпишите локальный шаблон кода перед запуском:
nuclei -duc -code -t templates/CVE-2026-45185.yaml -sign
Запустите против уязвимой лаборатории:
nuclei -code \
-t templates/CVE-2026-45185.yaml \
-u 127.0.0.1:2525 \
-var [email protected] \
-debug
Ожидаемый результат:
CVE-2026-45185: vulnerable response oracle matched
Запустите против исправленной лаборатории:
nuclei -code \
-t templates/CVE-2026-45185.yaml \
-u 127.0.0.1:2526 \
-var [email protected] \
-debug
Ожидаемый результат:
no match
NO-MATCH: patched-like response: NOOP succeeded after split trigger
Обратите внимание, что протокол code в nuclei не выполняется по умолчанию, поэтому требуется -code.
Nuclei также блокирует неподписанные шаблоны code. Если локальный закрытый ключ nuclei
защищён парольной фразой, запустите команду подписи в интерактивном
терминале и введите эту парольную фразу. Переподписывайте после каждого изменения
шаблона, так как дайджест покрывает содержимое шаблона.
На этих скриншотах показан результат оракула ответов локальной лаборатории после того, как шаблон был подписан. Это доказательство проверки для описанного выше различия ответов в одной сессии, а не прямое доказательство отладчика или ASAN внутренней записи UAF.
Уязвимая лаборатория Exim 4.99.2 GnuTLS на 127.0.0.1:2525:

Исправленная лаборатория Exim 4.99.3 GnuTLS на 127.0.0.1:2526:

Суть этой CVE — не проверка баннера SMTP или версии. Шаблону необходимо создать следующий переход состояния транспорта на том же TCP-соединении:
обычное SMTP EHLO
-> STARTTLS
-> рукопожатие TLS на том же TCP-соединении
-> TLS EHLO / MAIL FROM / RCPT TO / BDAT 70 LAST
-> первые 69 байт тела BDAT как данные приложения TLS
-> TLS close_notify без закрытия TCP-сокета
-> последний байт тела в открытом виде на том же TCP-соединении
-> проверка ответа на NOOP в той же сессии в открытом виде
Код Python внутри YAML-шаблона печатает фиксированный маркер только после того, как все следующие условия пройдены. Сопоставитель nuclei совпадает только с этим маркером.
Найдена идентификация Exim
И STARTTLS рекламируется в обычном EHLO
И CHUNKING рекламируется в обычном EHLO
И STARTTLS принят
И CHUNKING рекламируется в TLS EHLO
И MAIL FROM принят
И RCPT TO принят
И разделённый close_notify BDAT достигает первого завершения
И первое завершение содержит "250 OK id="
И ответ на NOOP в той же сессии в открытом виде содержит "421"
И ответ на NOOP в той же сессии в открытом виде содержит "lost input connection"
Шаблон не совпадает ни по одному из следующих сигналов по отдельности:
только версия
только таймаут
только разрыв соединения
только пустой ответ
отклонение получателя
только реклама STARTTLS/CHUNKING
Обе лаборатории обрабатывают разделённое сообщение BDAT до первого завершения.
250- 70 byte chunk, total 72
250 OK id=...
Разница проявляется, когда следующая SMTP-команда в открытом виде отправляется в той же SMTP-сессии.
Уязвимая 4.99.2:
NOOP -> 421 exim-lab.local lost input connection
QUIT -> 421 exim-lab.local lost input connection
RSET -> 421 exim-lab.local lost input connection
Исправленная 4.99.3:
NOOP -> 250 OK
QUIT -> 221 exim-lab.local closing connection
RSET -> 250 Reset OK
Интерпретация:
Наблюдение:
Обе лаборатории достигают завершения разделённого сообщения BDAT.
Только уязвимая лаборатория не может чисто вернуться к циклу следующей
команды SMTP в открытом виде в той же сессии.
Доказательство:
Ответный ответ уязвимой лаборатории — 421 lost input connection.
Ответный ответ исправленной лаборатории — 250 OK или 221 closing connection.
Вывод:
Это различие согласуется с различием в восстановлении стека/состояния приёма
после STARTTLS close_notify.