Внешняя проверка безопасности web/API Relayboard
Чистый синтетический пример того, как Defence фиксирует нарушение свойства системы, доказательства, исправление и границы вывода после ретеста.
- ID отчёта
- DEF-SYN-001
- Версия
- 1.0
- Состояние
- Финальный иллюстративный отчёт
- Период проверки
- 18–19 августа 2026
- Период ретеста
- 22 августа 2026
- Среда
- Синтетическая среда, близкая к production
- Текущая сборка
- relayboard-web 2026.08.22.3
- Сформирован
- 25 августа 2026 · 11:40 UTC
- Ответственный автор
- Команда проверки Defence
Краткий вывод
Отчёт не доказывает отсутствие других уязвимостей и не означает, что изменённая сборка прошла новую полную проверку.
На синтетических данных подтверждены два нарушения авторизации и одна проблема одноразового сценария.
Только SYN-01 имеет доказательство закрытия. В SYN-02 остался проблемный соседний маршрут. Для SYN-03 исправление заявлено, но ещё не проверено.
Незавершённая работа
- Закрыть действие observer в массовых операциях и повторить матрицу для всей группы маршрутов.
- Повторить проверку одноразовой ссылки на сборке 2026.08.22.3 до закрытия SYN-03.
- Согласовать окно нагрузочной проверки, чтобы снять блокер по ограничению частоты сессий.
Приоритетные действия
- 01Закрыть всю группу job-маршрутов
Исправление одиночного маршрута не защищает bulk-close. Нужна единая server-side policy и ретест запрещённой и разрешённой ролей.
Ответственный: API-команда - 02Проверить атомарное потребление ссылки
Заявленное исправление не является доказательством закрытия. Нужно повторить последовательное и конкурентное потребление ссылки.
Ответственный: Identity-команда - 03Снять блокер по throttling
Согласовать безопасное окно частоты запросов, чтобы применимое направление по сессиям получило честный статус.
Ответственный: Product + Defence
Система и границы
Зафиксированная поверхность включает один вымышленный multi-tenant продукт для полевых работ и только тестовые роли, пространства, задачи, экспорты и одноразовые ссылки.
- Веб-приложение
- app.relayboard.example
- HTTP API
- api.relayboard.example
- Сборка проверки
- relayboard-web 2026.08.18.5
- Сборка ретеста
- relayboard-web 2026.08.22.3
В границах
- Границы ролей и изоляция пространств на указанной web/API-поверхности.
- Только собственные тестовые роли и синтетические объекты.
- Ограниченное чтение и обратимые изменения тестовых состояний.
Вне границ
- Исходный код, cloud-конфигурация, внутренние сети, проверка доступности и сторонние ресурсы.
- Реальные данные клиентов, платежи, закрепление, сообщения и разрушительные действия.
- Предел воздействия
- Чтение синтетического объекта и обратимое изменение состояния. Воздействие на реальные пользовательские и финансовые данные запрещено.
- Условия остановки
- Неожиданные данные клиента, действующие секреты, реальные платежи, нестабильность сервиса или несогласованный хост останавливают проверку и запускают редактирование/эскалацию.
- Реестр методологий
- Модель внешней проверки Defence 1.0 · OWASP WSTG 4.2 · OWASP API Security Top 10 2023 · срез HackTricks от 18.08.2026
Реестр находок
Три воспроизведённых условия в порядке приоритета решения. Текущее состояние не зависит от критичности.
| ID | Находка | Ожидаемое свойство | Критичность | Текущее состояние |
|---|---|---|---|---|
| SYN-01 | Скачивание экспорта из другого пространства | Пространство сессии, пространство маршрута и владелец экспорта должны совпадать до выдачи файла. | Высокая | Закрыто ретестом |
| SYN-02 | Observer закрывает задачи через соседнюю операцию | Только dispatcher или owner может переводить задачу в closed во всех операциях группы маршрутов. | Средняя | Исправлено частично |
| SYN-03 | Одноразовая ссылка используется дважды | Одна синтетическая magic link создаёт не больше одной сессии, включая конкурентное использование. | Средняя | Исправлено — не проверено |
Скачивание экспорта из другого пространства
Закрыто для указанных условий на сборке 2026.08.22.3. Повторить после существенных изменений авторизации или маршрутизации хранения.
GET /v2/workspaces/{workspace_id}/exports/{export_id}/download- Синтетический экспорт exp_042 принадлежит ws_cobalt.
- Тестовая роль не состоит в ws_cobalt.
Три сигнала владения должны совпадать.
Сессия, маршрут и запись экспорта задают одну границу. Файл выдаётся только при совпадении всех трёх.
ДоказательстваEV-101
Workspace из маршрута не ограничил поиск экспорта.
Замена только синтетического ID экспорта вернула observer из ws_amber файл пространства ws_cobalt.
ДоказательстваEV-101 · EV-102
Поиск и policy привязаны к workspace.
Исправление требует составного поиска и server-side авторизации до передачи ответа, а не скрытой ссылки или нового текста в UI.
ДоказательстваEV-103
Запрещённый и разрешённый сценарии разделены корректно.
Чужой экспорт вернул 404 без тела, а разрешённый owner в своём workspace по-прежнему получил синтетический файл.
ДоказательстваEV-103
Доказательства
EV-101 · EV-102 · EV-103
Фрагмент синтетического запросаСинтетическое доказательство
GET /v2/workspaces/ws_cobalt/exports/exp_042/download Cookie: session=<REDACTED TEST SESSION> X-Test-Workspace: ws_amber
Ограниченный фрагмент · без публичного проверочного хэша
Фрагмент синтетического ответаСинтетическое доказательство
HTTP/2 200 content-type: text/csv content-length: 183 body: <SYNTHETIC EXPORT EXCERPT>
Ограниченный фрагмент · без публичного проверочного хэша
Контрольное наблюдениеСинтетическое доказательство
ws_amber owner + exp_amber_017 → 200 ws_amber observer + exp_042 → 200 before fix same session; only workspace/export pair changed
Ограниченный фрагмент · без публичного проверочного хэша
Граница последствий
- Ожидалось
- Чужой экспорт не возвращается, а сведения о существовании объекта не пересекают границу пространства.
- Наблюдалось
- Observer из ws_amber получил вымышленный CSV-экспорт ws_cobalt с HTTP 200.
- Доказано
- Пользователь одного синтетического пространства прочитал файл другого синтетического пространства.
- Возможно, но не доказано
- То же условие могло бы раскрывать другие экспорты при известном идентификаторе.
- Не доказано
- Реальные клиентские экспорты не запрашивались, не наблюдались и не сохранялись. Способы поиска идентификаторов не проверялись.
Поиск экспорта принимал export_id без привязки к workspace из маршрута до выдачи файла.
Исследовалось внешнее поведение. Исходный код, сборка framework policy и deployment-конфигурация не изучались.
Исправление
Искать экспорт по workspace_id + export_id, применять policy до передачи файла и возвращать нейтральный not-found ответ.
observer + foreign export → 200 + fileobserver + foreign export → 404 + no bodyowner + own export → 200 + fileМатрица ретеста
| Маршрут | Ожидалось | Наблюдалось | Доказательства | Зафиксированный результат |
|---|---|---|---|---|
| observer · ws_amber → exp_042 · ws_cobalt | 404 · empty body | 404 · empty body | EV-103 | Восстановлено |
| owner · ws_amber → exp_amber_017 | 200 · synthetic CSV | 200 · synthetic CSV | EV-103 | Контроль сработал |
Целевой ретест закрывает только записанное условие и не является новой полной проверкой изменённой сборки.
История находки
- Нарушение воспроизведено дваждыEV-101 · EV-102Подтверждено
- Исправление заявлено в новой сборкеBuild noteНужен ретест
- Повторены запрещённый и разрешённый сценарииEV-103Закрыто ретестом
Observer закрывает задачи через соседнюю операцию
Исправить сейчас. Пока bulk-close принимает observer, свойство нарушено и находку нельзя закрыть.
POST /v2/workspaces/{workspace_id}/jobs/{job_id}/closePOST /v2/workspaces/{workspace_id}/jobs/bulk-close- Обе задачи находятся в состоянии in_progress.
- UI не показывает observer действия закрытия.
Одно правило ролей действует для всей группы операций.
Скрытая кнопка не является контролем. Одиночный и массовый переход должны применять одно серверное разрешение.
ДоказательстваEV-201
Прямые запросы обошли скрытое действие UI.
Observer изменил состояние синтетических задач в обоих handler, хотя UI не показывал эти действия.
ДоказательстваEV-201 · EV-202
Policy добавили только в одиночный маршрут.
Первое исправление изменило один handler. Это прогресс, но не восстановление свойства для всей группы маршрутов.
ДоказательстваEV-203
Соседний маршрут оставляет находку открытой.
Одиночный close отказал observer и разрешил dispatcher. Bulk-close всё ещё принял observer, поэтому исправление остаётся частичным.
ДоказательстваEV-203 · EV-204
Доказательства
EV-201 · EV-202 · EV-203 · EV-204
Фрагмент синтетического запросаСинтетическое доказательство
POST /v2/workspaces/ws_amber/jobs/bulk-close
Cookie: session=<REDACTED TEST SESSION>
body: { job_ids: [job_amber_204] }Ограниченный фрагмент · без публичного проверочного хэша
Фрагмент синтетического ответаСинтетическое доказательство
HTTP/2 202
body: { accepted: 1 }
observed state: job_amber_204 = closedОграниченный фрагмент · без публичного проверочного хэша
Контрольное наблюдениеСинтетическое доказательство
observer + single close → 403 after fix dispatcher + single close → 202 observer + bulk-close → 202 after fix
Ограниченный фрагмент · без публичного проверочного хэша
Граница последствий
- Ожидалось
- Observer получает отказ, а обе задачи остаются in_progress в одиночной и массовой операциях.
- Наблюдалось
- До исправления обе операции принимали observer. Ретест закрыл одиночный маршрут, но bulk-close всё ещё вернул 202 и закрыл вторую синтетическую задачу.
- Доказано
- Observer изменил состояние собственной синтетической задачи через серверную операцию, предназначенную для dispatcher/owner.
- Возможно, но не доказано
- Другие соседние операции процесса также могут непоследовательно применять это правило.
- Не доказано
- Проверялась только указанная группа close и собственные синтетические задачи. Клиентские задачи и внешние эффекты не затрагивались.
Авторизация была добавлена в один handler, а не в общую policy перехода состояния для всей группы маршрутов.
Поведение handler указывает на это условие, но размещение контроля в исходном коде независимо не проверялось.
Исправление
Применить единую server-side policy к одиночной и массовой операциям, атомарно проверять текущее состояние и повторить все сочетания ролей и операций.
observer + single/bulk close → 202 + state changeobserver + single close → 403 · bulk-close → 202observer + every close operation → 403 + unchangedМатрица ретеста
| Маршрут | Ожидалось | Наблюдалось | Доказательства | Зафиксированный результат |
|---|---|---|---|---|
| observer → jobs/{id}/close | 403 · unchanged | 403 · unchanged | EV-203 | Восстановлено |
| dispatcher → jobs/{id}/close | 202 · closed | 202 · closed | EV-203 | Контроль сработал |
| observer → jobs/bulk-close | 403 · unchanged | 202 · closed | EV-204 | Всё ещё нарушено |
Целевой ретест закрывает только записанное условие и не является новой полной проверкой изменённой сборки.
История находки
- Нарушения single и bulk воспроизведеныEV-201 · EV-202Подтверждено
- Policy одиночного маршрута развёрнутаBuild noteИсправление заявлено
- Ретест группы маршрутов нашёл остаточное нарушениеEV-203 · EV-204Исправлено частично
Одноразовая ссылка используется дважды
Не закрывать. Повторить последовательную и конкурентную матрицы на указанной сборке и сохранить контроль разрешённого сценария.
POST /v2/auth/magic-links/{token}/consume- Для test_user_07 выпущена одна синтетическая ссылка.
- В отчёте не сохраняются реальные mailbox, token или session value.
Одна возможность создаёт одну сессию.
Token reference — одноразовая возможность. Потребление и выдача сессии должны быть одним атомарным решением.
ДоказательстваEV-301
Та же ссылка выдала вторую сессию.
Оба последовательных запроса завершились успешно. Сохранены только references сессий и метаданные ответа.
ДоказательстваEV-301 · EV-302
Заявлено атомарное исправление consume.
Команда сообщает о переносе фиксации одноразового состояния до выдачи сессии. Это вход для ретеста, а не доказательство закрытия.
Доказательства—
Матрица определена, но не выполнена.
Находка остаётся открытой, пока разрешённый consume и последовательные/конкурентные запреты не дадут доказательства на указанной сборке.
Доказательства—
Доказательства
EV-301 · EV-302
Фрагмент синтетического запросаСинтетическое доказательство
POST /v2/auth/magic-links/<SYNTHETIC TOKEN REF>/consume attempt 1 → 201 · session_ref_A attempt 2 → 201 · session_ref_B
Ограниченный фрагмент · без публичного проверочного хэша
Фрагмент синтетического ответаСинтетическое доказательство
token value: not retained session values: not retained two distinct synthetic session references recorded
Ограниченный фрагмент · без публичного проверочного хэша
Контрольное наблюдениеСинтетическое доказательство
fresh link + first consume → expected 201 same link + second consume → observed 201 concurrent replay → not tested
Ограниченный фрагмент · без публичного проверочного хэша
Граница последствий
- Ожидалось
- Первое корректное использование создаёт одну сессию; все следующие завершаются отказом без новой сессии.
- Наблюдалось
- Два последовательных запроса с одной синтетической token-reference создали две разные тестовые сессии.
- Доказано
- Одна синтетическая возможность аутентификации была повторно использована для создания двух тестовых сессий.
- Возможно, но не доказано
- Скопированная или задержанная ссылка могла бы оставаться пригодной после первого использования.
- Не доказано
- Доказан только последовательный replay на собственных тестовых данных. Конкурентный сценарий и реальная доставка почты не проверялись.
Поведение consume не делало состояние одноразового использования видимым до выдачи второй сессии.
Атомарность и место транзакции — гипотеза исправления; исходный код и транзакция хранилища не наблюдались.
Исправление
Заявленное исправление: атомарно помечать ссылку использованной до выдачи сессии и отклонять все последующие или конкурентные запросы.
same link → session A + session Batomic consume before session issuance201 once · later/concurrent attempts deniedМатрица ретеста
| Маршрут | Ожидалось | Наблюдалось | Доказательства | Зафиксированный результат |
|---|---|---|---|---|
| новая ссылка → первый consume | 201 · one session | Не выполнено | — | Ожидает |
| та же ссылка → последовательный replay | denied · zero new sessions | Не выполнено | — | Ожидает |
| та же ссылка → конкурентный replay | one success maximum | Не выполнено | — | Ожидает |
Целевой ретест закрывает только записанное условие и не является новой полной проверкой изменённой сборки.
История находки
- Последовательный replay воспроизведён дваждыEV-301 · EV-302Подтверждено
- Заявлено атомарное исправление consumeBuild noteИсправлено — не проверено
Реестр покрытия
15 записанных направлений · 12 применимых. Каждая строка сохраняет обоснование применимости, точную проверку, доказательства, статус и ограничение.
| Направление | Ожидаемое свойство | Применимость | Точная проверка | Зафиксированный результат | Статус направления | Ограничение |
|---|---|---|---|---|---|---|
| IDENT-01Идентификация и сессии | Завершение сессии аннулирует собственную тестовую сессию. | ПрименимоПрисутствуют session endpoints. | TC-011Выйти и повторить прежнюю session reference. | Повторный запрос отклонён. | Контроль сработал | Другие устройства и долгоживущие сессии не проверялись. |
| IDENT-04Идентификация и сессии | Magic link одноразовая. | ПрименимоПрисутствует аутентификация по magic link. | TC-301Использовать одну собственную синтетическую ссылку дважды. | Созданы две сессии.EV-301 · EV-302 | Направление с находкой | Конкурентный replay не проверен. |
| IDENT-06Идентификация и сессии | Повторные попытки аутентификации ограничены. | ПрименимоЕсть публичный маршрут аутентификации. | TC-061Ограниченное окно проверки throttling. | Окно проверки не согласовано. | Заблокировано | Продолжить после согласования предела частоты запросов. |
| AUTHZ-02Авторизация и изоляция | Владение workspace ограничивает скачивание экспортов. | ПрименимоЕсть маршрут экспорта для нескольких workspace. | TC-101Подмена cross-workspace ID на собственных ролях. | Нарушение воспроизведено и закрыто целевым ретестом.EV-101 · EV-102 · EV-103 | Направление с находкой | Закрытие относится только к указанным маршруту и сборке. |
| AUTHZ-03Авторизация и изоляция | Ролевые ограничения действуют для всех close-операций. | ПрименимоЕсть роли observer, dispatcher и owner. | TC-201Матрица ролей × одиночные/массовые операции. | Соседний bulk-маршрут всё ещё нарушен.EV-201 · EV-202 · EV-203 · EV-204 | Направление с находкой | Другие группы workflow проверялись отдельно. |
| FLOW-02Процессы и состояния | Переход в closed требует разрешённой роли и корректного состояния. | ПрименимоПрисутствует workflow состояния job. | TC-204Запрещённые/разрешённые роли в соседних операциях. | Исправлено частично.EV-203 · EV-204 | Направление с находкой | Разрушительные или внешние эффекты job не запускались. |
| FLOW-04Процессы и состояния | Одноразовое состояние атомарно. | ПрименимоConsume magic link меняет состояние аутентификации. | TC-302Последовательный replay; конкурентный запланирован. | Последовательное нарушение воспроизведено; исправление не проверено.EV-301 · EV-302 | Направление с находкой | Конкурентность остаётся неизвестной. |
| INPUT-03Ввод и серверное поведение | Тип загрузки проверяется по содержимому и ограниченному размеру. | ПрименимоЕсть загрузка синтетических вложений. | TC-403Несовпадающие extension/content и ограниченный oversized fixture. | Отклонено до сохранения.EV-401 | Контроль сработал | Malware processing и downstream previewers были вне границ. |
| API-02API и интеграции | Неподписанный webhook не может изменить job. | ПрименимоЕсть синтетический входящий webhook. | TC-502Неподписанные и просроченные синтетические события. | Отклонены до изменения состояния.EV-501 | Контроль сработал | Доставка провайдера и replay не проверялись. |
| SERVER-01Ввод и серверное поведение | Некорректные идентификаторы не раскрывают детали stack. | ПрименимоЕсть параметризованные публичные маршруты. | TC-601Некорректные и неизвестные синтетические ID. | Нейтральные ответы 404/400. | Контроль сработал | Ошибки не-HTTP сервисов не проверялись. |
| EXPOSURE-01Внешняя поверхность | Указанная поверхность не раскрывает backup/debug artifacts. | ПрименимоПубличные web/API hosts входят в scope. | TC-701Известные пути artifacts и найденные публичные references. | Artifact не воспроизведён. | Контроль сработал | Соседние hosts остались пассивным inventory. |
| API-06API и интеграции | Авторизация graph-запросов соблюдается. | Не применимоGraph endpoint или ссылка клиента не обнаружены. | Только проверка применимости. | Отсутствует в зафиксированной поверхности. | Не применимо | Пересмотреть при добавлении graph endpoint. |
| PAY-01Платежи | Платёжные переходы проверяют сумму и роль. | Не применимоВ синтетической системе Relayboard нет платежей. | Только проверка применимости. | Платёжная поверхность отсутствует. | Не применимо | Нет вывода о внешних billing-системах. |
| THIRD-01Сторонние эффекты | Внешние сообщения не принимают неавторизованные triggers. | ПрименимоУпоминается production messaging integration. | TC-801Только пассивная проверка конфигурации и маршрута. | Активная доставка исключена пределом воздействия. | Вне границ | Нужно отдельное разрешение и синтетический sink провайдера. |
| SESSION-09Идентификация и сессии | Поведение сессии после смены credentials ограничено. | Не определеноПоведение смены credentials не наблюдалось извне. | Внешнее наблюдение на собственных аккаунтах. | Нет надёжного статуса. | Неизвестно | Нужна контролируемая смена или evidence из source/config. |
Сработавшие контроли
- Условие
- Неподписанные и просроченные события отправлены в собственный синтетический workspace.
- Наблюдалось
- Оба отклонены до изменения синтетической задачи.
- Доказательства
- EV-501
- Ограничение
- Доставка, retry и replay со стороны провайдера не проверялись.
- Условие
- Собственный text fixture, объявленный image, и ограниченный oversized fixture.
- Наблюдалось
- Оба вернули validation response без ссылки на сохранённый объект.
- Доказательства
- EV-401
- Ограничение
- Malware scanning и downstream rendering были вне scope.
Ограничения и приложения
Все системы, названия, маршруты, идентификаторы, записи, временные метки, ответы и результаты в этом публичном отчёте созданы для чистого синтетического примера. Он показывает структуру отчёта Defence и ход рассуждений, а не клиентский результат, сертификацию или независимую валидацию Defence.
Ограничения и неизвестное
Только внешнее поведение
Исходный код, infrastructure-as-code, cloud policy, внутренние сервисы и процессы сотрудников не проверялись.
Для таких выводов нужна отдельная внутренняя проверка.Только указанные сборки
Наблюдения относятся к указанным сборкам и условиям каждой находки.
Существенные изменения авторизации, маршрутов, ролей или workflow переоткрывают связанные направления.Блокер rate-limit
Согласованный предел воздействия не включал частоту запросов для meaningful throttling test.
Согласовать окно, максимальную частоту, stop threshold и контакт.Нет абсолютной гарантии
Полное применимое покрытие фиксирует статус каждого применимого направления в зафиксированном scope. Оно не доказывает отсутствие всех уязвимостей.
Повторить после существенного изменения продукта или появления новых разрешений/evidence.Реестр доказательств
| ID | Тип / связь | Текущая сборка | Время | Обработка / происхождение |
|---|---|---|---|---|
| EV-101 | Фрагмент request/responseSYN-01 · TC-101 | relayboard-web 2026.08.18.5 | 2026-08-18 10:14 UTC | Session value и body минимизированыСинтетическое доказательство |
| EV-102 | Контроль воспроизведенияSYN-01 · TC-102 | relayboard-web 2026.08.18.5 | 2026-08-18 10:22 UTC | Только синтетические IDПроизводное от EV-101 |
| EV-103 | Матрица ретестаSYN-01 · TC-103 | relayboard-web 2026.08.22.3 | 2026-08-22 09:18 UTC | Response bodies минимизированыПроизводное от EV-101 |
| EV-201 | Воспроизведение single-routeSYN-02 · TC-201 | relayboard-web 2026.08.18.5 | 2026-08-18 13:06 UTC | Только собственная jobСинтетическое доказательство |
| EV-202 | Воспроизведение sibling-routeSYN-02 · TC-202 | relayboard-web 2026.08.18.5 | 2026-08-18 13:19 UTC | Только собственная jobПроизводное от EV-201 |
| EV-203 | Ретест single-routeSYN-02 · TC-203 | relayboard-web 2026.08.22.3 | 2026-08-22 10:02 UTC | Собственные роли и jobsПроизводное от EV-201 |
| EV-204 | Ретест sibling-routeSYN-02 · TC-204 | relayboard-web 2026.08.22.3 | 2026-08-22 10:11 UTC | Собственные роли и jobsПроизводное от EV-202 |
| EV-301 | Фрагмент sequential replaySYN-03 · TC-301 | relayboard-web 2026.08.18.5 | 2026-08-19 08:44 UTC | Token и sessions не сохраненыСинтетическое доказательство |
| EV-302 | Контроль воспроизведенияSYN-03 · TC-302 | relayboard-web 2026.08.18.5 | 2026-08-19 08:51 UTC | Только referencesПроизводное от EV-301 |
| EV-401 | Контроль загрузкиINPUT-03 · TC-403 | relayboard-web 2026.08.18.5 | 2026-08-19 11:05 UTC | Только синтетические fixturesСинтетическое доказательство |
| EV-501 | Контроль webhookAPI-02 · TC-502 | relayboard-web 2026.08.18.5 | 2026-08-19 12:27 UTC | Синтетические event IDsСинтетическое доказательство |
Ограниченный фрагмент · без публичного проверочного хэша
Реестр методологий
- Defence external review model1.0
- Scope, граф свойств, evidence, dispositions и честность завершения.
- OWASP Web Security Testing Guide4.2
- Направления и методы web-тестирования.
- OWASP API Security Top 102023
- Линзы API-авторизации, ресурсов, процессов и inventory.
- HackTrickssnapshot 2026-08-18
- Подсказки техник; сами по себе не являются доказательством.
История версий
- v0.9Черновик проверки
Исходные находки и реестр покрытия.
- v1.0Финальный иллюстративный отчёт
Добавлены исправления, целевой ретест и текущее состояние без перезаписи исходных доказательств.