Расследования по эндпоинтам

Записи расследований в SQLite: статус проверки, теги, заметки и улики.

Когда при первичном отборе (triage) всплывает эндпоинт, за которым стоит последить — кандидат на IDOR, маршрут логина с rate limit, эндпоинт выпуска токенов, — к нему можно привязать постоянную запись расследования. Каждая запись привязана к маршруту из каталога, содержит статус проверки, произвольные теги и поле заметок для улик и шагов воспроизведения. Хранится она в той же базе SQLite, что и импортированные захваты, поэтому переживает перезапуски.

Где живут записи расследований

Записи редактируются из каталога маршрутов в API-лаборатории. Откройте рабочее пространство API, разверните строку маршрута в каталоге — и рядом с панелями схемы, GraphQL и конвейера декодирования для этого маршрута появится секция Investigation record. Когда запись существует, в заголовке секции отображается текущий статус в виде бейджа.

Запись привязана к ключу эндпоинта из записи каталога, поэтому у одного маршрута ровно одна запись. О том, как группируются маршруты, см. /docs/ru/api-re/catalog/.

Создание и редактирование записи

  1. Разверните нужный маршрут в каталоге.
  2. В секции Investigation record выберите статус проверки из выпадающего списка (по умолчанию — unreviewed).
  3. Введите теги через запятую, например auth, BOLA, tier-1.
  4. Запишите улики и шаги воспроизведения в текстовом поле.
  5. Нажмите Save. Бейдж статуса обновится, а запись будет сохранена в SQLite.

Чтобы удалить запись, нажмите кнопку с корзиной рядом с Save. Удаление стирает строку целиком; маршрут возвращается в состояние «записи нет» (а не сбрасывается в unreviewed).

Состояния статуса проверки

Статус — это состояние рабочего процесса расследования. Бэкенд отклоняет любое значение вне этого набора с кодом HTTP 400.

СтатусЗначениеБейдж
unreviewedПо умолчанию; замечен, но ещё не оценённейтральный
reviewedОценён, действий не требуетзелёный
interestingСтоит более глубокого расследованияянтарный
vulnerableПодтверждённая находка на авторизованной целикрасный
false-positiveСигнал опровергнутнейтральный

[!NOTE] vulnerable предназначен для находок, подтверждённых на системах, которые вам разрешено тестировать. Зафиксируйте в заметках область авторизации, чтобы запись была самодостаточной при последующем пересмотре.

Теги

Теги — это короткие метки для группировки и фильтрации. При сохранении бэкенд нормализует их:

  • У каждого тега обрезаются окружающие пробелы.
  • Пустые теги отбрасываются.
  • Дубликаты удаляются без учёта регистра (auth, Auth и AUTH схлопываются в первый встреченный вариант написания).
  • Тег длиннее 64 символов или 31-й по счёту тег не проходит валидацию с кодом HTTP 400.

В редакторе вводите теги одной строкой через запятую; при сохранении они разбиваются и обрезаются.

Заметки и улики

Поле заметок — это область свободного текста для сути расследования: наблюдаемого поведения, шагов воспроизведения, результатов replay, владельцев и способов устранения. Плейсхолдер редактора подсказывает: Evidence, reproduction notes, owner, remediation….

Размер заметок ограничен 20 000 символов; ввод большей длины отклоняется с кодом HTTP 400. Отдельного объекта улик нет — статус отражает состояние рабочего процесса, а поле заметок — это место, где живут улики и детали воспроизведения. Вставляйте конкретные фрагменты запросов/ответов и шаги, воспроизводящие поведение, чтобы находка была самодостаточной.

[!TIP] Если находка зависит от replay, укажите использованные переменные replay и выражения вывода (derivation expressions), чтобы воспроизведение было повторяемым. См. /docs/ru/replay/variables/ и /docs/ru/replay/workbench/.

Как записи сохраняются

Записи хранятся в таблице endpoint_annotations базы SQLite Traffic Jam (по умолчанию .traffic-jam/traffic-jam-v2.sqlite3, переопределяется через TRAFFIC_JAM_DB_PATH):

create table if not exists endpoint_annotations (
    endpoint_key text primary key,
    status text not null default 'unreviewed',
    tags_json text not null default '[]',
    notes text not null default '',
    updated_at text not null
);

endpoint_key — первичный ключ, поэтому сохранение работает как upsert: повторное сохранение для того же маршрута перезаписывает статус, теги и заметки и обновляет updated_at (хранится как метка времени RFC 3339 в UTC). Теги хранятся как JSON-массив в tags_json. Вторичный индекс по (status, updated_at desc) обеспечивает выборку по статусу и давности. Поскольку данные находятся в базе захватов, записи переживают перезапуски API и перемещаются вместе с файлом базы.

Как записи связаны с каталогом и replay

Связь между записью расследования и остальным рабочим пространством — ключ эндпоинта в формате method:host:pathTemplate, например:

GET:api.example.test:/users/{id}

Это тот же ключ, который идентифицирует маршрут в каталоге и служит ключом для конвейеров декодирования и анализа сигнатур по маршруту. Таким образом, запись аннотирует маршрут каталога напрямую: задержка маршрута, доля ошибок и число сессий в каталоге — это контекст вокруг вашей находки, а replay запускается из той же записи каталога. Используйте поле заметок, чтобы привязать запись к конкретным прогонам replay и пассивным находкам (см. /docs/ru/security/findings/).

REST API

Фронтенд обращается к небольшому JSON API, которым можно управлять и напрямую:

МетодПутьНазначение
GET/api/endpoint-annotationsСписок всех записей, сначала самые свежие по updated_at
POST/api/endpoint-annotationsСоздать или обновить запись (upsert по endpointKey)
DELETE/api/endpoint-annotations/{endpointKey}Удалить одну запись

Тело POST:

{
  "endpointKey": "GET:api.example.test:/users/{id}",
  "status": "interesting",
  "tags": ["auth", "BOLA"],
  "notes": "User A can read user B's profile by swapping the id."
}

Ошибки валидации (отсутствует endpointKey, неизвестный статус, слишком длинные теги или заметки) возвращают HTTP 400; удаление несуществующего ключа возвращает HTTP 404. Запросы должны удовлетворять тем же правилам origin и capability-токена, что и остальная часть API.

Рабочий процесс: от интересного эндпоинта к задокументированной находке

  1. Найдите кандидата в поиске или пассивных находках и откройте его маршрут в каталоге.
  2. Переведите запись в interesting и пометьте тегом предполагаемый класс (BOLA, auth-bypass, rate-limit).
  3. Выполните replay маршрута — варьируя учётные данные или ID в пути в соответствии с гипотезой — и зафиксируйте в заметках подтверждающий запрос/ответ. См. /docs/ru/replay/workbench/.
  4. После подтверждения на авторизованной цели переведите статус в vulnerable и запишите область, влияние и способ устранения. Если сигнал не воспроизводится, пометьте его как false-positive.
  5. Оставьте запись на месте как постоянный аудиторский след; она хранится в SQLite вместе с захватом, который её породил.

Документация Traffic Jam. Собрано с помощью Hugo.