Shadow API: когда HAR знает больше, чем OpenAPI
Синтетический research-shot: схема проблемы, контроля, evidence и ретеста в фирменной лабораторной стилистике Virusologia.
Коротко: Если у команды есть только OpenAPI, она видит желаемую архитектуру. Если есть только трафик, она не понимает намерение. Полезный аудит строится на diff между схемой, HAR, gateway-логами и правами ролей.

Проблема

Документация API почти всегда отстаёт от продакшена. Старые маршруты остаются ради обратной совместимости, тестовые методы случайно публикуются наружу, а новая авторизация появляется не везде одновременно.

Когда команда смотрит только на OpenAPI или только на сканер, она не видит архитектурный дрейф. Именно там часто живут shadow endpoint-ы, незакрытые debug-methods и неожиданные пути обхода rate limit или auth middleware.

Решение

Нужно строить inventory из нескольких источников: OpenAPI, HAR, reverse proxy access log, application route dump и release notes. Только сравнение этих слоёв показывает, что реально живёт в perimeter и какие маршруты никто больше не контролирует.

После inventory полезно разделить маршруты на documented, observed_only, doc_only и privileged. Это сразу даёт разговор не про payload, а про ownership: кто отвечает за endpoint, почему он опубликован и как проверить его безопасно.

Что проверить руками

  • Собрать HAR из обычного пользовательского сценария и административного сценария.
  • Извлечь список методов и paths из OpenAPI и сравнить его с observed traffic.
  • Отдельно пометить observed_only endpoint-ы с object id, file download, export или debug semantics.
  • Проверить, не отличаются ли для shadow routes security headers, auth chain и rate-limit policy.

Типичные ошибки

  • Считать, что undocumented endpoint автоматически нерелевантен для аудита.
  • Сканировать весь observed surface одинаково, не разделяя публичные и role-bound routes.
  • Закрывать риск формулировкой 'не используется', не проверив gateway, code owners и release path.

Defensive checklist

  • Есть diff между OpenAPI и observed traffic.
  • Observed-only endpoints назначены владельцам.
  • Role-bound methods проверены read-only replay или manual trace.
  • Retest критерий описывает, как drift будет ловиться на следующем релизе.

Безопасный пример кода

Diff OpenAPI и observed traffic по path/method. Пример рассчитан на owned/lab-среду и показывает инженерную логику проверки, а не эксплуатационную цепочку.

import json
from collections import defaultdict
from pathlib import Path


def openapi_ops(path: str) -> set[tuple[str, str]]:
    spec = json.loads(Path(path).read_text(encoding="utf-8"))
    result = set()
    for route, methods in spec.get("paths", {}).items():
        for method in methods:
            result.add((method.upper(), route))
    return result


def observed_ops(path: str) -> set[tuple[str, str]]:
    data = json.loads(Path(path).read_text(encoding="utf-8"))
    result = set()
    for item in data:
        result.add((item["method"].upper(), item["path"]))
    return result


doc = openapi_ops("openapi.json")
obs = observed_ops("traffic_inventory.json")
print("observed_only", sorted(obs - doc)[:10])
print("doc_only", sorted(doc - obs)[:10])

Как это должно попасть в отчёт

  • Coverage: documented, observed_only, doc_only, privileged_only.
  • Evidence: HAR/reference log, affected role, route owner, auth chain notes.
  • Retest: release pipeline или nightly inventory должен поднимать alert на новый drift.
Этическая рамка: материал предназначен для defensive security, исследования собственных систем, controlled labs и подготовки remediation. Здесь нет вредоносных payload-цепочек, persistence-инструкций и шагов для несанкционированного доступа.