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

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

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

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

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

Категории

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

CVE-2026-34828

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

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

Популярное

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

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

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

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

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

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, выданный до сброса, по-прежнему успешно аутентифицировался

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

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

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

root@kitploit:~
HTTP/1.1 200 OK
Content-Type: application/json

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

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

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

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

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

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

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

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

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

root@kitploit:~
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.

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


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

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

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

Во-первых

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

Одно и то же свойство безопасности нарушалось и при:

  • неаутентифицированном сбросе пароля, инициированном восстановлением
  • аутентифицированной смене пароля внутри сессии

Во-вторых

Это затруднило списание проблемы как случайной бизнес-логики.

Это явно была более широкая слабость управления сессиями:

  • состояние пароля изменилось,
  • но существующие сессии оставались доверенными.

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


Проверка TOTP

Я также протестировал процесс сброса на учётной записи с включённым TOTP, потому что хотел выяснить, не ослабляет ли и не обходит ли сброс пароля ожидания, связанные с 2FA.

Что я подтвердил:

  • сброс пароля по-прежнему выполнялся успешно
  • TOTP оставался включённым
  • новый вход с новым паролем по-прежнему перенаправлял на шаг 2FA
  • то есть это не был прямой обход 2FA

Это было полезной проверкой границы.

Она правильно сузила проблему.

Уязвимость заключалась не в том, что:

  • «сброс пароля отключает TOTP»
  • или «сброс пароля обходит TOTP»

Реальной проблемой оставалось:

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

Это более чёткий и более защитимый вывод.


Серьёзность и классификация

Эта проблема была обоснованно классифицирована как High (высокая).

Ключевое воздействие здесь — устойчивый несанкционированный доступ после действий по восстановлению безопасности учётной записи.

Классификация в бюллетене:

  • CWE-613: Недостаточный срок действия сессии
  • CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N

Это логично.

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

Это реальная и защитимая уязвимость управления сессиями.


Почему об этом всё равно стоило сообщить

Некоторые недооценивают ошибки сохранения сессий, полагая, что кража сессии — это уже «game over».

Это слишком упрощённо.

Настоящий вопрос — что происходит после того, как жертва замечает, что что-то не так, и предпринимает действия.

Если:

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

то восстановление учётной записи неполно.

Это не просто неудобное поведение. Это сбой безопасности в модели восстановления.

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


Анализ исправления

Мейнтейнер исправил проблему в коммите:

root@kitploit:~
db82035

Основное направление исправления — ровно то, что было нужно этой ошибке:

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

Это правильное устранение, потому что оно нацелено на реальное нарушенное свойство безопасности:

прежнее доверие должно умирать при изменении учётных данных

Хорошее исправление для этого класса ошибок — не про изменение проверки пароля. Оно про отзыв ранее активного состояния сессии, привязанного к учётной записи.

Именно это восстанавливает реальное восстановление доступа.


Раскрытие

Об этой проблеме было сообщено конфиденциально через поток отчётов о безопасности GitHub.

Мейнтейнер:

  • рассмотрел отчёт
  • принял его как проблему безопасности
  • исправил поведение
  • и проблеме был присвоен:

CVE-2026-34828

Во время обработки бюллетеня всплыл один момент — охват.

Первоначальный отчёт включал оба случая:

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

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

Итоговым результатом стал CVE-2026-34828.


Чему на самом деле учит эта ошибка

Главный урок здесь прост:

изменения учётных данных недостаточно, если прежнее аутентифицированное доверие всё ещё живо.

Многие разработчики мыслят в терминах:

  • корректности пароля
  • корректности токена
  • успешности входа
  • действительности токена сброса

Эти вещи важны.

Но реальная граница безопасности шире:

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

В данном случае ответ должен был быть:

  • старые сессии

И listmonk этого не делал.

Вот в чём настоящий вывод.


Ключевые моменты

  • отзыв сессий — часть безопасности восстановления учётной записи
  • сброс пароля не должен оставлять ранее выданные сессии живыми
  • смена пароля не должна оставлять параллельные активные сессии живыми
  • кража сессии остаётся значимой, если события восстановления не отзывают доверие
  • тестирование нескольких связанных процессов делает отчёт сильнее
  • сужение круга поиска и уход от ложных следов, таких как обход 2FA, помогает сохранить вывод чистым

Заключение

Эта уязвимость — не про изощрённые полезные нагрузки или хитрые трюки с парсерами.

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

В listmonk пароль изменился.
Действие по восстановлению завершилось.
Но старая сессия злоумышленника всё ещё жила.

Именно поэтому это стало CVE-2026-34828.

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