Apache OpenMeetings 9.1.0 — высокий уровень — удалённо — IDOR — сохранение календаря LOGIN перезаписывает встречу и закрывает публичную комнату
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · openmeetings-calendar-save-idor
Класс: IDOR Доступ: Удалённый
Apache OpenMeetings 9.1.0 (9773c59e) - Apache Software Foundation
Любой пользователь с LOGIN может выполнить POST /services/calendar/ с id чужой встречи и опустить owner. Предикат сохранения никогда не загружает сохранённого владельца. Затем CalendarMapper, а за ним RoomMapper, записывают closed / ispublic / name в привязанную комнату. Зарегистрированный пользователь перезаписывает чужую встречу и закрывает публичную конференц-комнату.
| ID | CVE пока нет |
| Класс | IDOR |
| Доступ | Удалённый (аутентифицированный LOGIN REST) |
| CWE | CWE-639, CWE-284 |
| CVSS | Высокий: 7.6 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:L |
| Продукт | Apache OpenMeetings |
| Затронуто | 9.1.0 (9773c59e1af327bf988018e661f456ae9997c29f) |
| Аутентификация | LOGIN (по умолчанию самостоятельная регистрация выдаёт его) |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | только 127.0.0.1:18150. apache/openmeetings:min-9.1.0 плюс Temurin 21. |
Я зафиксировал тег 9.1.0, peel 9773c59e1af327bf988018e661f456ae9997c29f (2026-07-14). Последний GA. Java 21. Не master.
Зарегистрироваться (мастер allowFrontendRegister=true) или иметь любой пароль LOGIN. POST /openmeetings/services/user/login выдаёт SID. Идентификаторы встреч последовательны. Публичная комната с id 2 — это штатная конференц-комната.
| Метод | Точка записи | Привилегия |
|---|---|---|
POST /services/calendar/?sid= форма appointment JSON, owner опущен, id жертвы | предикат CalendarWebService.save (CalendarWebService.java:310-329) | Целостность (доказано в лаборатории): перезапись заголовка, времени, участников. В лаборатории: заголовок стал OPENMEETINGS-CALENDAR-SAVE-WITNESS, владелец 2→3. |
То же сохранение; room.closed=true | RoomMapper.get записывает в управляемую сущность (RoomMapper.java:62-92), затем dao.update | Целостность + доступность (доказано в лаборатории): публичная конференц-комната сохранилась с closed=true, isPublic=false. SOAP GET /room/2 вернул это. |
GET заголовка/диапазона атакующим после сохранения | DTO ответа — это строка после записи | Разведка (доказано в лаборатории): заголовок-свидетель. Диапазон жертвы пуст после кражи владельца. |
Доказано в лаборатории vs выведено: HTTP 200 при сохранении, заголовок, кража владельца, закрытие комнаты — это лаборатория. Биты вместимости / модерации на том же маппере — выведены.
Требуется: сетевой путь к /openmeetings/services. Учётная запись LOGIN. id встречи жертвы (последовательный, или создать свою и подождать). Открытая регистрация по умолчанию.
| Поверхность | Почему |
|---|---|
DELETE /calendar/{id} | владелец или SOAP/ADMIN. Обычный LOGIN не может удалять чужие. |
| Чтение диапазона / next / заголовка | ограничено владельцем. Атакующий не получает чистого чтения исходной строки. |
| Запись MP4 | другой ACL (RecordingResourceReference). |
| Список по userid только через SOAP | Right.SOAP. У зарегистрированных пользователей по умолчанию его нет. |
| Неаутентифицированное сохранение | performCall требует SID с LOGIN. |
9.1.0 закрыл CVE-2026-49488 (чтение файлов ОС через fuid whiteboard). Я продолжил охоту за id объектов REST. Удаление календаря проверяет a.isOwner(sd.getUserId()). Сохранение календаря проверяет владельца из DTO запроса, или null. CalendarMapper.get загружает appointmentDao.get(dto.getId()) без ограничения по владельцу. Затем RoomMapper помечает JPA-сущность комнаты как изменённую перед dao.update.
Этот аккаунт интеграции с LMS — SOAP, перечисляющий каждую встречу. Этот остаток — LOGIN против владельца.
cd lab
./run.sh
Loopback https://127.0.0.1:18150/openmeetings. Официальный docker-администратор om_admin / 1Q2w3e4r5t^y. Самоподписанный TLS. Свидетель последней строки:
SUCCESS OPENMEETINGS-CALENDAR-SAVE-WITNESS
Загрузить сохранённую встречу перед сохранением. Требовать a.isOwner(caller), если это не SOAP/ADMIN. Не применять записи RoomMapper к комнате, которую вызывающий не может модерировать. Рассматривать опущенного владельца как «сохранить сохранённого владельца», а не «вызывающий становится владельцем».
Abraxas Labs - https://abraxaslabs.tech - https://github.com/abraxas - https://x.com/abraxas_null - [email protected]
Поставщик: [email protected]