Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-34828 — listmonk: сохранение сессии после сброса пароля и смены пароля | Kitploit
Инструменты/GitHubGitHub/0xmrma/cve-2026-34828
Анализ уязвимостейЭксплуатацияВеб-безопасностьТестирование на ПроникновениеАутентификация
GitHub0xmrma/cve-2026-34828

CVE-2026-34828

listmonk: сохранение сессии после сброса пароля и смены пароля

Репозиторий
156 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-34828

listmonk: сохранение сессий после сброса и смены пароля

Введение

Я обнаружил эту проблему при проверке listmonk — open-source менеджера новостных рассылок и списков рассылки, задавшись простым вопросом с точки зрения безопасности:

Когда пользователь меняет или сбрасывает пароль, действительно ли приложение завершает уже выданные сессии?

В данном случае ответ был — нет.

Ранее выданные аутентифицированные сессии оставались действительными и после:

  • сброса пароля
  • смены пароля

Это означало, что украденный сессионный cookie мог пережить именно те события безопасности, на которые пользователи рассчитывают при восстановлении доступа к своей учётной записи.

Проблема была принята, и ей присвоен CVE-2026-34828.

Проект: listmonk на GitHub
CVE: CVE-2026-34828

Затронут listmonk — широко используемый проект с 5M+ скачиваний Docker.

photo0

Цепочка атаки

stolen authenticated session → victim resets or changes password → old session remains valid → attacker retains account access after credential recovery


Что делает listmonk

listmonk — это self-hosted менеджер списков рассылки и новостных рассылок.

Он предоставляет:

  • аутентификацию администратора
  • управление пользователями
  • создание кампаний
  • управление подписчиками
  • настройки SMTP и эксплуатационные настройки
  • администрирование через браузер

Это означает, что его модель сессий является реальной границей безопасности.

Важный вопрос здесь заключался не в том, поддерживает ли listmonk сброс пароля.

Настоящий вопрос был таков:

Действительно ли сброс или смена пароля отзывают сохранённый злоумышленником доступ, если сессия уже была украдена?

В данном случае — нет.


Почему эта ошибка стоила внимания

Многие обзоры безопасности слишком узко сосредоточены на обходе входа в систему и очевидных повышениях привилегий.

При этом упускается важный класс уязвимостей:

сбои восстановления доступа

Если пользователь меняет или сбрасывает пароль, это действие должно быть значимым.
Оно должно снижать доверие к прежним учётным данным и прежнему состоянию аутентификации.

Если у злоумышленника уже есть действительная сессия и эта сессия переживает событие восстановления, значит жертва на самом деле не восстановила учётную запись полностью.

Именно это и было здесь.

Это не ошибка проверки входа. Это не проблема криптографии. Это не сбой хеширования паролей.

Это был сбой жизненного цикла сессий:

  • состояние пароля изменилось,
  • восстановление учётной записи произошло,
  • но старые сессии по-прежнему считались доверенными.

Этого достаточно, чтобы возникла реальная уязвимость.


Граница, на которой я сосредоточился

Я не подходил к listmonk, беспорядочно дёргая эндпоинты в надежде, что какой-нибудь сломается.

Более сильный путь — сначала определить самую ценную границу доверия.

Для программного обеспечения с интенсивной аутентификацией одна из лучших границ для тестирования такова:

Отзывают ли чувствительные к безопасности изменения учётной записи ранее доверенные сессии?

Обычно этот вопрос становится интересным вокруг:

  • сброса пароля
  • смены пароля
  • изменений 2FA
  • процессов восстановления учётной записи

В listmonk самый сильный сигнал исходил от первых двух пунктов.

Именно там проблема стала очевидной.


Корневая причина

Ошибка заключалась не в том, что смена пароля не работала.

Ошибка заключалась в том, что сессии переживали смену пароля.

Из анализа исходного кода, процесс сброса пароля:

  • генерировал и проверял одноразовый токен сброса,
  • обновлял пароль,
  • создавал новую сессию,

но видимого отзыва старых сессий не было.

Та же картина наблюдалась в процессе аутентифицированной смены пароля:

  • пароль обновлялся,
  • но ранее выданные сессии не инвалидировались.

Это поведение в точности совпало с результатами живого тестирования.

Области кода, которые я просмотрел:

  • cmd/auth.go — поведение забытого пароля/сброса
  • cmd/users.go — аутентифицированные обновления профиля
  • internal/core/users.go — обработка обновления пароля

Почему это эксплуатируемо

Потому что кража сессии — это реальное условие атаки.

Как только злоумышленник получает действительный аутентифицированный сессионный cookie любым способом, например:

  • компрометация браузера
  • вредоносное ПО
  • доступ к общему рабочему месту
  • XSS в другом компоненте
  • утечка через прокси или отладку
  • случайное раскрытие cookie

жертва должна иметь возможность прекратить сохранённый злоумышленником доступ, сменив или сбросив пароль.

Здесь она этого сделать не могла.

Цепочка атаки была прямолинейной:

  • у злоумышленника есть действительный сессионный cookie
  • жертва выполняет сброс или смену пароля
  • старый пароль становится недействительным
  • новый пароль работает
  • старая сессия злоумышленника по-прежнему успешно аутентифицируется

В этом и заключается вся уязвимость.


Почему это проблема безопасности, а не просто особенность приложения

Ключевое различие — сохранение доступа после восстановления.

Многие приложения рассматривают смену пароля как чисто событие на уровне учётных данных. Этого недостаточно.

Настоящий вопрос не в том:

«Изменилось ли значение пароля в хранилище?»

Настоящий вопрос в том:

«Были ли отозваны отношения доверия, связанные со старыми сессиями?»

В listmonk — нет.

Это превращает то, что могло быть обычным обслуживанием учётной записи, в неполное восстановление безопасности.

В этом разница между:

  • обычной непрерывностью сессии
  • и реальной уязвимостью безопасности

PoC

Я подтвердил проблему в двух отдельных процессах.

Случай 1: Сброс пароля не отзывает существующие сессии

Сначала я создал обычного тестового пользователя и вошёл в систему, сохранив аутентифицированный сессионный cookie.

Затем я запустил процесс забытого пароля, перехватил ссылку для сброса и сбросил пароль.

После сброса:

  • старый пароль больше не работал
  • новый пароль работал
  • но старый сессионный cookie, выданный до сброса, по-прежнему успешно аутентифицировался

Показательный проверочный запрос выглядел так:

GET /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<old_pre_reset_session>

И сервер по-прежнему возвращал:

HTTP/1.1 200 OK
Content-Type: application/json

с аутентифицированным профилем.

Это подтвердило основной тезис:

  • восстановление завершено,
  • учётные данные изменены,
  • но доверие к существующей сессии сохранилось.

Случай 2: Смена пароля не отзывает параллельные активные сессии

Затем я подтвердил тот же класс ошибки в процессе аутентифицированной смены пароля.

Я дважды вошёл в систему под одним и тем же пользователем и сохранил две действительные аутентифицированные сессии:

  • сессия A
  • сессия B

Используя сессию A, я сменил пароль через эндпоинт обновления профиля.

Пример запроса:

PUT /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<session_A>
Content-Type: application/json

{
  "name":"victim1",
  "email":"[email protected]",
  "password":"VictimChanged123"
}

После этого:

  • старый пароль больше не работал
  • новый пароль работал
  • но сессия B оставалась действительной

Последующий запрос с использованием сессии B по-прежнему возвращал аутентифицированные данные из /api/profile.

Это доказало, что проблема не ограничивалась процессом забытого пароля/сброса.
Она затрагивала и обычную аутентифицированную смену пароля.


Почему важны оба воспроизведения

Одного воспроизведения уже было бы достаточно, чтобы показать проблему.

Но подтверждение обоих процессов было важно по двум причинам.

Во-первых

Это показало, что ошибка не изолирована в одном пограничном пути восстановления.

Скачать инструмент