Программное обеспечение OpenReception для записи на прием предоставляет платформу для записи на прием со сквозным шифрованием. Поток резервирования нового клиента в версиях 1.0.1 и более ранних состоит из трех вызовов: «bootstrap-challenge» (возвращает 16-битный запрос PoW с ведущими шестнадцатеричными нулями «difficulty=4»), «bootstrap-verify» (проверяет PoW и выдает токен доступа к резервированию на предъявителя) и «create-new-client» (использует токен и создает туннель и первую встречу). Токен правильно привязывается к TenantId, TunnelId, clientPublicKey и emailHash, но никогда к ChannelId.
Схема запроса «bootstrap-challenge» даже не принимает «channelId», а полезная нагрузка выданного токена не содержит информации о канале. Независимо от этого сервисная функция createNewClientWithAppointment проверяет только «channel.archived = false». Проверка Channel.isPublic, защищающая addAppointmentToTunnel, отсутствует в пути нового клиента.
Комбинация означает: злоумышленник нормально завершает процесс начальной загрузки (16-битный PoW, на стандартном оборудовании он завершается менее чем за одну секунду, без ограничения скорости за пределами хранилища дроссельной заслонки), получает действительный токен доступа к резервированию, а затем отправляет полезную нагрузку `create-new-client` с `channelId`, указывающим на частный (`isPublic = false`) канал. Бронирование получает статус «ПОДТВЕРЖДЕНО», если целевой канал имеет значение «requiresConfirmation = false» (по умолчанию), в противном случае — как «НОВЫЙ». Пользовательский интерфейс, ориентированный на пациента, не перечисляет частные каналы в своем средстве выбора (`/api/public/channels` правильно фильтрует `isPublic = true`), поэтому идентификатор канала должен быть получен вне диапазона.
Сопутствующий поиск V-10 (конечная точка расписания раскрывает частные каналы) обеспечивает именно это: один неаутентифицированный GET раскрывает каждый идентификатор частного канала для любого арендатора. V-10 и V-11 вместе делают частные каналы полностью доступными для анонимных злоумышленников. На момент публикации известных исправленных версий не существует.
Показать оригинальное описание (EN)
OpenReception's appointment booking software provides an end-to-end encrypted appointment booking platform. The new-client booking flow in versions 1.0.1 and prior consists of three calls: `bootstrap-challenge` (returns a 16-bit PoW challenge with `difficulty=4` leading hex zeroes), `bootstrap-verify` (validates the PoW and issues a Bearer booking access token), and `create-new-client` (consumes the token and creates the tunnel and first appointment). The token correctly binds to `tenantId`, `tunnelId`, `clientPublicKey`, and `emailHash`, but never to `channelId`. The `bootstrap-challenge` request schema does not even accept a `channelId`, and the issued token's payload contains no channel information. Independently, the service function `createNewClientWithAppointment` checks only `channel.archived = false`. The `channel.isPublic` check that protects `addAppointmentToTunnel` is missing in the new-client path. The combination means: an attacker completes the bootstrap flow normally (16-bit PoW, completes in well under one second on commodity hardware, no rate limiting beyond the throttle store), receives a valid booking access token, and then submits the `create-new-client` payload with `channelId` pointing to a private (`isPublic = false`) channel. The booking lands as `CONFIRMED` if the target channel has `requiresConfirmation = false` (the default), otherwise as `NEW`. The patient-facing UI does not list private channels in its picker (`/api/public/channels` correctly filters `isPublic = true`), so the channel ID must be obtained out of band. The companion finding V-10 (schedule endpoint discloses private channels) provides exactly that: a single unauthenticated GET reveals every private channel ID for any tenant. V-10 plus V-11 together make private channels fully reachable to anonymous attackers. As of time of publication, no known patched versions are available.
Характеристики атаки
Последствия
Строка CVSS v3.1