
Element Web v1.12.29 — High — Remote — Session — фрагмент guest creds стирает реальную сессию перед whoami
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · element-fragment-guest
Разбор: https://abraxaslabs.tech/research/element-fragment-guest
Element Web v1.12.29 - Element / New Vector
Класс: Уничтожение сессии Доступ: Удалённый
Lifecycle.loadSession предпочитает guest_user_id и guest_access_token из хэша URL вместо restoreSessionFromStorage. Гостевой режим включён по умолчанию (enableGuest={!config.disable_guests}). В config.json на app.element.io не задан disable_guests. onTokenLoginCompleted удаляет только параметры SSO и OIDC. Он никогда не удаляет гостевые ключи. В url_utils.ts уже есть комментарий, что эти параметры фрагмента выглядят неиспользуемыми. Они всё равно побеждают.
Любой, кто сможет заставить вошедшего пользователя открыть URL с хэшем, содержащим гостевые параметры фрагмента, разлогинит его и уничтожит локальные криптоданные. Достаточно мусорного токена. whoami никогда не вызывается.
| ID | CVE пока нет |
| CWE | CWE-384 / CWE-352 / CWE-613 |
| CVSS | Высокий: 7.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H |
| Продукт | Element Web |
| Затронуто | Тег v1.12.29 v1.12.29 (2d90d6b7b601ecb9ccdf81239a43b4396b4b0c9e). Гостевой режим включён (по умолчанию). |
| Аутентификация | неаутентифицированный атакующий. Жертва должна открыть (или перезагрузить) URL. |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1 |
Заставить вошедшего пользователя открыть URL с хэшем, содержащим гостевые параметры фрагмента. Клиент разлогинивает его, уничтожает локальные криптоданные и может оставить его в гостевой сессии атакующего. Это разлогинивание и уничтожение криптоданных. Это не кража настоящего токена. Это не RCE в ОС.
| Привилегия | Метод / точка воздействия | Разведка / целостность / доступность | Доказано в лаборатории или выведено |
|---|---|---|---|
| Разбор гостевых учётных данных из хэша | url_utils.ts guest: { keys: ["guest_user_id", "guest_access_token"], location: "fragment" } | Целостность выбора сессии | Доказано в лаборатории. #/home?guest_user_id=...&guest_access_token=... стало guest_params. Только в строке запроса — не сработало. |
| Предпочтение гостевой сессии сохранённой негостевой | Ветка Lifecycle.loadSession, где гостевая сессия имеет приоритет, лог Using guest access credentials | Целостность | Доказано в лаборатории. Заранее созданная @victim:example.org не была восстановлена. |
| Уничтожение localStorage, аккаунта IndexedDB, sessionStorage, криптоданных | doSetLoggedIn(..., clearStorageEnabled=true), затем clearStorage() | Целостность / доступность локальной сессии | Доказано в лаборатории. crypto_empty=yes, прежний токен исчез. |
| Пропуск проверки токена | Гостевой путь никогда не вызывает /_matrix/client/v3/account/whoami | Целостность | Доказано в лаборатории. whoami_called=no. Мусорный токен not-a-real-token всё равно привёл к уничтожению данных. |
| Сохранение гостевых учётных данных атакующего | persistCredentials после уничтожения | Целостность | Доказано в лаборатории. after_user=@x:example.org, after_token=not-a-real-token, mx_is_guest=true. |
| Фиксация на реальном госте на домашнем сервере по умолчанию | То же сохранение, если гостевой токен действителен | Целостность | Выведено. В лаборатории использовался мусорный токен, поэтому входа на живой домашний сервер не было. |
| Повторение при перезагрузке | Гостевые ключи остаются в хэше; onTokenLoginCompleted их не удаляет | Целостность | Выведено из закреплённого app.tsx. В лаборатории URL открывался один раз. |
Закрыто по этому остатку: украсть настоящий access token (он удаляется, а не похищается). OS RCE / LPE (Desktop nodeIntegration: false, sandbox). Живой Element SPA (how=gadget). Query-string ?guest_user_id= (только фрагмент). disable_guests: true сохраняет не-гостевую сессию. Пропатченный loadSession, который игнорирует гостя при наличии не-гостевой сессии, также сохраняет её.
Те же остатки пина: vector: Windows drive-letter, Univention ICS javascript: href.
Я закрепил Element Web v1.12.29 после релиза на GitHub 22 сентября 2026 года. SSO loginToken передаётся только через query и вырезается после использования. Гостевые ключи по-прежнему находятся во фрагменте и побеждают при восстановлении. Комментарий в url_utils.ts — это подсказка: они уже сомневались, что эти ключи специфицированы.
Уже зафиксированные неверные пути: трактовка query-string ?guest_user_id= как вектора (ключи живут в хэше); называть это кражей токена (настоящий токен удаляется, а не отправляется); ожидание disable_guests в конфиге app.element.io (он не задан). Обратная оболочка. Театр.
Гаджет функций пина. Не живой контейнер Element Web. how=gadget.
python3 element-fragment-guest-Abraxas-Labs.py
или
cd lab
./run.sh
Цель — только http://127.0.0.1:19600. Проект Compose element-fragment-guest. Стек разворачивается после запуска.
SUCCESS element-fragment-guest how=gadget guest-wipe=yes prior-kept=no garbage-token=yes disable-guests-keeps=yes ELEMENT-FRAGMENT-GUEST-WITNESS
Игнорировать параметры гостевого фрагмента, если не гостевая сессия уже существует. Проверять гостевой токен с помощью /_matrix/client/v3/account/whoami перед clearStorage. Удалять guest_user_id и guest_access_token так же, как удаляются токены SSO. По умолчанию disable_guests: true для размещённого app.element.io.
Lifecycle.ts (loadSession с приоритетом гостя)url_utils.tsapp.tsx (enableGuest={!config.disable_guests})GNU Affero GPL v3.0. См. LICENSE. Только для лаборатории с loopback. Без гарантий.