System Design Space
Граф знанийНастройки

Обновлено: 25 июня 2026 г. в 05:45

API Security Patterns

средний

Практические паттерны защиты API: authn/authz, rate limiting, schema validation, anti-replay, abuse prevention и secure API lifecycle.

API уязвим не из-за одного забытого заголовка, а когда у него с самого начала слабый security contract.

Глава собирает защиту API из нескольких слоев: identity и authorization checks, rate limiting, schema validation, anti-replay, abuse prevention и secure lifecycle самого интерфейса.

В архитектурных обсуждениях через нее удобно разбирать public edge, internal APIs, trust zones и то, почему безопасность интерфейса начинается еще до первой ручки в OpenAPI.

Практическая польза главы

Практика проектирования

Используйте материал по паттернах защиты API, контрактах безопасности и abuse mitigation, чтобы формировать архитектурные security-требования до этапа реализации.

Качество решений

Проверяйте решения через модель угроз, security invariants и управляемость контролей в production, а не только через чеклист соответствия.

Аргументация на интервью

Стройте ответ в формате threat -> control -> residual risk, показывая связь между бизнес-сценарием и техническими мерами защиты.

Формулировка компромиссов

Явно описывайте компромиссы по паттернах защиты API, контрактах безопасности и abuse mitigation: UX friction, накладная задержка (latency overhead), стоимость сопровождения и требования compliance.

Контекст

OWASP Top 10 в контексте System Design

Безопасность API — это конкретизация рисков OWASP под конкретную поверхность программного интерфейса вашей системы.

Открыть главу

Программный интерфейс (API) — самая открытая поверхность системы: его адрес известен, документация публична, а за ней лежат чужие данные и деньги. API Security Patterns — это набор решений, который держит интерфейс рабочим под нагрузкой, в среде и при активном противнике. Цельной «безопасности» не бывает — она собирается из протоколов аутентификации, политики доступа, защиты от злоупотреблений (abuse) и наблюдаемости, и каждый слой стоит денег и латентности.

Базовые паттерны защиты API

Строгая аутентификация и краткоживущие токены

/, взаимная -аутентификация между сервисами, ротация токенов и понятная стратегия отзыва.

Точная авторизация

Аутентификация говорит «кто», но защищает «что можно»: ролевые и атрибутные правила, права в рамках арендатора, движок политик и запрет по умолчанию — на шлюзе и в каждом сервисе.

Проверка входных данных и схемы

Всё, что пришло снаружи, — недоверенный ввод: строгая проверка по JSON-схеме и контракту OpenAPI, нормализация и отклонение неизвестных полей, чтобы лишний атрибут не дотянулся до модели.

Ограничение частоты и защита от злоупотреблений

Квоты на пользователя, приложение и арендатора держат стоимость и доступность под контролем; добавьте сдерживание всплесков, обнаружение ботов и адаптивное ограничение трафика.

Защита от повторного воспроизведения и подпись запроса

, отметка времени и HMAC/подпись, политика допустимого расхождения часов и окно действия запроса.

Сетевая модель нулевого доверия

Внутренняя сеть — не периметр доверия: ни один внутренний программный интерфейс (API) не считается своим по умолчанию, отсюда взаимная аутентификация и сегментация сети.

Типовые сценарии атак

BOLA/IDOR на object-level API

Риск: Пользователь получает доступ к чужим объектам при корректной аутентификации, но слабой авторизации.

Митигация: Проверки политики на уровне объектов, , запрет по умолчанию и обязательная проверка владельца объекта.

Token replay

Риск: Перехваченный токен используется повторно и позволяет выполнять привилегированные действия.

Митигация: Краткоживущие токены, с отметкой времени, sender-constrained токены и .

Массовое назначение полей (mass assignment) и злоупотребление схемой

Риск: Запрос несёт лишние поля, и без явного фильтра они дописываются в модель — атакующий меняет атрибут, который менять не должен.

Митигация: Схема со строгим разрешённым списком полей, отклонение неизвестных полей и серверная проверка того, какие поля вообще принадлежат этому клиенту.

Массовый сбор данных через API и злоупотребление бизнес-логикой

Риск: Атака не ломает аутентификацию — она пользуется легитимными эндпоинтами для массового сбора данных или фрода, и обычные проверки доступа её не замечают.

Митигация: Адаптивные лимиты запросов, поведенческие сигналы, квоты на арендатора и многослойная защита от ботов.

Spec

OAuth 2.0 DPoP (RFC 9449)

Спецификация proof-of-possession на уровне приложения: структура proof-токена JWT, jkt-привязка и серверные одноразовые значения.

Открыть документ RFC 9449

Sender-constrained токены: DPoP и mTLS-bound

работает по принципу «кто принёс, тот и владелец»: перехваченный токен полностью рабочий. Sender-constrained токен криптографически привязан к ключу клиента — кража токена без кражи ключа бесполезна. Два стандартных способа привязки разобраны ниже.

DPoP — proof-of-possession на уровне приложения

RFC 9449

Как работает

  1. Клиент генерирует пару ключей: остаётся у него (в браузере — non-extractable ключ WebCrypto), уходит серверу.
  2. На каждый запрос клиент создаёт DPoP proof — компактный с заголовком typ: "dpop+jwt" и публичным ключом в jwk, подписанный приватным ключом.
  3. Внутри proof: jti (уникальный идентификатор для replay-детекции), htm (-метод), htu (URI без query и фрагмента), iat; при вызове API — ещё ath, SHA-256-хэш .
  4. Сервер авторизации кладёт в токен подтверждение cnf.jkt — base64url JWK SHA-256 thumbprint публичного ключа. Токен передаётся как Authorization: DPoP <token>, а не Bearer.
  5. Resource server проверяет подпись proof, совпадение htm/htu с фактическим запросом, свежесть iat/jti и равенство jkt ключу из proof.
  6. Против заранее заготовленных proof сервер выдаёт в заголовке DPoP-Nonce и отвечает ошибкой use_dpop_nonce; клиент повторяет запрос, включив его в proof.

Против чего: Украденный без приватного ключа бесполезен; привязка htm/htu не даёт переиграть запрос на другой эндпоинт; серверный ломает proof, заготовленные при XSS-краже.

Цена: Подпись на каждый запрос (CPU и латентность), серверное хранилище jti для replay-детекции, дополнительный цикл ретраев на серверном (use_dpop_nonce) и заметно более сложные клиентские SDK.

mTLS-bound токены — привязка через взаимную аутентификацию канала

RFC 8705

Как работает

  1. Клиент устанавливает -соединение (взаимный ) с сервером авторизации и предъявляет : PKI-метод tls_client_auth (сертификат от доверенного ) или self_signed_tls_client_auth (ключ зарегистрирован через jwks).
  2. Сервер кладёт в выданный токен подтверждение cnf с членом x5t#S256 — base64url SHA-256-хэш DER-кодировки клиентского сертификата.
  3. Каждый вызов API тоже идёт по : resource server берёт сертификат из -слоя и сравнивает его хэш со значением x5t#S256 в токене.
  4. Хэши не совпали — запрос отклоняется с 401 и кодом invalid_token: токен предъявил не тот клиент, которому он был выдан.

Против чего: Тот же proof-of-possession, что у DPoP, но без подписи на каждый запрос: канал сам доказывает владение ключом. Бонус — одновременно закрывает и аутентификацию клиента перед эндпоинтом выдачи токенов.

Цена: до edge — боль при и на балансировщике (сертификат нужно пробрасывать до приложения), плюс PKI и ; для браузерных практически недоступен.

МеханизмГде уместенПочему
DPoPПубличные клиенты: (SPA), мобильные приложения, CLI — везде, где клиентский сертификат недоступен.Работает на уровне приложения, проходит через любые и прокси без проброса сертификата.
mTLS-boundB2B-интеграции, межсервисные вызовы, финансовые API с управляемыми клиентами.Нет криптографии на каждый запрос; естественно ложится на сервисную сетку и существующую PKI.
Оба валидныFAPI 2.0 Security Profile требует sender-constrained токены и допускает оба механизма.Чистый Bearer для high-stakes API в финансовом профиле уже не считается достаточным.

Подписи запросов: HMAC и HTTP Message Signatures

Токен подтверждает, кто вызывает API; запроса — что именно он отправил: метод, путь, заголовки и тело не были изменены по дороге. Образец HMAC-схемы — AWS Signature Version 4.

HMAC-подпись по образцу AWS SigV4

  1. Канонизация. Запрос приводится к единственно возможной форме: метод, URI-encoded путь, отсортированный query string, канонические заголовки (lowercase, отсортированы, без лишних пробелов), список подписанных заголовков и SHA-256-хэш тела. Любая неоднозначность здесь — будущий «signature mismatch».
  2. String to sign. Из канонического запроса собирается строка: алгоритм AWS4-HMAC-SHA256, timestamp ISO 8601, область действия ключа YYYYMMDD/region/service/aws4_request и хэш канонического запроса.
  3. Производный ключ. Секрет не подписывает напрямую: цепочка HMAC-SHA256 («AWS4»+секрет → дата → регион → сервис → aws4_request) даёт ключ, ограниченный днём и сервисом, — утечка подписи не раскрывает долгоживущий секрет.
  4. Заголовок. В заголовок авторизации Authorization уходят алгоритм, Credential (ключ + область действия), SignedHeaders и Signature. Сервер повторяет все шаги и сравнивает результат; расхождение часов больше 15 минут — отказ RequestTimeTooSkewed.

Против чего: подделка и несанкционированное изменение запроса (tampering); timestamp в подписи ограничивает окно повторного воспроизведения; производный ключ снижает урон от утечки.

Цена: хрупкая — прокси переписывают заголовки и нормализуют URL, отладка «signature mismatch» мучительна, а общий секрет нужно защищать на обеих сторонах.

HTTP Message Signatures (RFC 9421) — стандартизация

  • Два заголовка: Signature-Input перечисляет покрытые компоненты и параметры подписи, Signature несёт само значение.
  • Подписываются явно выбранные компоненты: derived-компоненты @method, @target-uri, @authority, @path, @query, @status — плюс любые -заголовки по имени.
  • Параметры подписи — created, expires, keyid, alg, nonce, tag: окно против повторов и идентификация ключа встроены в стандарт.
  • Алгоритмы: RSASSA-PSS, ECDSA P-256/P-384, EdDSA (Ed25519) и HMAC-SHA256 — асимметричная подпись снимает проблему общего секрета на двух сторонах.
  • Зачем стандарт: вместо зоопарка самодельных схем (клоны SigV4, draft-cavage) — подпись, которая переживает доброкачественные трансформации прокси, потому что покрывает только явно выбранные компоненты.

Защита от повторного воспроизведения и идемпотентность

перехваченного запроса — атака; повтор запроса клиентом после таймаута — норма. Два механизма ниже различают эти случаи и работают в паре.

Окно timestamp + nonce

  1. Клиент кладёт в подписанную часть запроса timestamp и уникальный одноразовый .
  2. Сервер отклоняет запросы вне допустимого окна (типично минуты, с поправкой на ); у AWS SigV4 это 15 минут.
  3. Внутри окна сервер запоминает увиденные (кеш с , равным окну) и отклоняет повторы. Окно ограничивает размер хранилища: вечно хранить nonce не нужно.
  4. В кластере -хранилище обязано быть общим для всех реплик — иначе атакующий повторит запрос через соседнюю реплику, которая этот nonce ещё не видела.

Цена: общее -хранилище на пути каждого запроса, ложные отказы при рассинхронизации часов, а ширина окна — компромисс между размером хранилища и допуском для медленных клиентов.

Ключи идемпотентности (idempotency keys) — смежный механизм

  • Клиент генерирует (обычно UUID) на бизнес-операцию и передаёт его в заголовке Idempotency-Key, который стандартизирует черновик IETF httpapi.
  • Сервер атомарно («проверь-и-запиши» одной операцией) сохраняет ключ и результат первого выполнения — код и тело ответа, включая ошибки. Повтор с тем же ключом возвращает сохранённый результат, не выполняя операцию заново.
  • Ключи живут ограниченно: Stripe, чья реализация стала образцом для черновика IETF, удаляет ключи старше 24 часов.
  • Разница с : она отклоняет повтор — это атака; ключ идемпотентности возвращает тот же результат — это легитимный . В write-API нужны оба механизма одновременно.

Ограничение частоты запросов и квоты на API-шлюзе

От обычно ждут защиты от отказа в обслуживании (), но тот же контроль удерживает счёт за инфраструктуру, изолирует арендаторов друг от друга и сдерживает массовый сбор данных. Базовый алгоритм на шлюзах — «ведро токенов» (token bucket).

Механизм

  • Token bucket: на каждый ключ лимита заводится «ведро» ёмкостью B токенов, пополняемое со скоростью R в секунду. Запрос забирает токен; пустое ведро — ответ 429 с Retry-After для повторной попытки. B задаёт допустимый burst, R — устойчивую скорость.
  • Ключ лимита — аутентифицированный principal: API-ключ, client_id, пользователь, тенант. На лимиты складываются в иерархию: per-user внутри per-tenant внутри глобального.
  • Rate limit и — разные контроли: лимит защищает систему от всплесков на горизонте секунд, квота — бизнес-контракт на период (сутки, месяц, тариф). Шлюз должен считать оба.
  • На распределённом шлюзе счётчики либо в общем сторе (Redis — точно, но дороже по латентности), либо локальные с фоновой синхронизацией (быстро, но допускает кратковременный перебор лимита).

Частые ошибки

  • Лимит по IP: за /CGNAT мобильного оператора один адрес — тысячи легитимных пользователей, а атакующий ротирует IP. Ключом должен быть principal; IP — только для неаутентифицированного трафика.
  • Лимитировать только после аутентификации: сама проверка аутентификации (хэширование, поход к ) — дорогая операция, которую нужно прикрыть дешёвым лимитом до неё.
  • 429 без Retry-After и без джиттера на клиенте — повторные попытки приходят синхронной волной, и лимит сам порождает .
  • Один глобальный лимит без : шумный сосед выедает общий бюджет, и страдают все остальные.

Секреты клиентов: client_secret против private_key_jwt

Машинные клиенты (client credentials, серверные интеграции) должны как-то аутентифицироваться перед эндпоинтом выдачи токенов. Выбор механизма определяет, что именно утечёт при компрометации и насколько больно ротировать.

client_secret — общий секрет

  • — симметричный : он передаётся на эндпоинт выдачи токенов при каждом обращении и должен храниться на обеих сторонах.
  • Слабости: утечка на любой из сторон равна компрометации; секрет просачивается в логи, конфиги и CI; массовая ротация требует координации с каждым клиентом.

private_key_jwt — client assertion (RFC 7523)

  1. Клиент держит ; сервер авторизации знает только публичный — зарегистрированный напрямую или опубликованный через jwks_uri.
  2. На эндпоинт выдачи токенов клиент отправляет параметр client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer и client_assertion, подписанный приватным ключом (документ RFC 7523; в OpenID Connect метод называется private_key_jwt).
  3. В assertion: iss и sub равны client_id, aud указывает на сервер авторизации, короткий exp и jti против повторного использования.
  4. Сервер проверяет подпись по зарегистрированному ключу. Секрет не передаётся по сети вовсе, а компрометация базы сервера не раскрывает ключ клиента — там только публичные части.

Ротация

  • Ротация секрета — всегда окно двух значений: регистрируем новый секрет, перекатываем клиентов, отзываем старый. Без поддержки двух активных секретов ротация превращается в простой.
  • jwks_uri делает почти бесплатной: клиент публикует новый ключ рядом со старым, сервер подхватывает его сам — координация не нужна.
  • Любому секрету — срок жизни и алерт на приближение истечения: «вечный» client_secret в проде равен по профилю риска.

Secure API lifecycle

Без замкнутого цикла безопасности защита программного интерфейса быстро рассыпается на точечные правки после каждого инцидента. Ниже — рабочий цикл, где каждый этап готовит входы для следующего и возвращает обратную связь назад в проектирование.

Безопасный APIцикл защиты1. Проектированиеthreat model + API contract2. Разработкаsecure implementation3. Верификацияsecurity tests + release gates4. Выкаткаgateway + policy enforcement5. Эксплуатацияtelemetry + incident response

Текущий этап

1. Проектирование

Определяем границы доверия, abuse-сценарии и security-требования до написания кода: кто вызывает API, какие данные передаются, где возможна эскалация привилегий.

  • • STRIDE/LINDDUN по группам endpoint'ов и бизнес-флоу
  • • Явная модель AuthN/AuthZ, tenant isolation и классификация данных
  • • Security acceptance criteria в OpenAPI/ADR

Следующий этап

2. Разработка

Встраиваем проверки в pipeline: код, зависимости и секреты автоматически проверяются до merge и продвижения build-артефакта.

  • • SAST + secret scanning + dependency/SBOM scan
  • • Lint/OpenAPI checks: auth scopes, schema strictness, rate-limit hints
  • • Стандартные middleware/библиотеки для auth, validation и signature checks

Матрица контролей безопасности API

ЗонаКонтролиКак валидироватьДействие при провале
Identity and AccessOAuth2/OIDC, mTLS, JWT claim checks, RBAC/ABAC.AuthN/AuthZ test suites, forbidden-path integration tests.Block request, log policy decision, alert security owner.
Input and SchemaOpenAPI contract validation, canonicalization, strict parsing.Negative tests, fuzzing, schema drift checks in CI.Reject payload with explicit error code, track abuse signal.
Abuse and AvailabilityRate limits, WAF rules, idempotency keys, replay protection.Load/adversarial tests, bot simulation, replay scenario drills.Throttle/block source, auto-escalate if pattern persists.
Sensitive DataField-level masking, minimization, encryption in transit and at rest.Log inspection checks, DLP scans, PII-safe response snapshots.Mask output, quarantine endpoint, open compliance incident.
Observability and ResponseAudit logs, security metrics, trace correlation with tenant context.Incident playbook drills, detection rule validation, MTTR reviews.Activate containment playbook and temporary hardening policies.

Data

Data Governance & Compliance

Без политик работы с данными именно программный интерфейс становится главным каналом утечки персональных данных (PII) — он отдаёт ровно то, что вернул в ответе.

Открыть главу

Sensitive data rules for APIs

Чувствительные поля не отдаются по умолчанию — только то, что попало в явный разрешённый список полей; забыли поле в списке — клиент его не увидит, а это безопаснее обратного промаха.

Персональные данные (PII) в логах и трассировке маскируются или вовсе не пишутся: лог живёт дольше запроса и попадает в больше рук.

Версионирование программного интерфейса не должно ослаблять гарантии безопасности старых клиентов — иначе апгрейд превращается в скрытую регрессию защиты.

Публичный и внутренний интерфейсы — это разные уровни доверия: у них разные базовые требования к безопасности и разные ключи доступа.

Текст ошибки не должен выдавать внутреннее устройство — имена сервисов, структуру базы данных и правила политик доступа: это бесплатная разведка для атакующего.

Операционные метрики

Unauthorized request block rate

Target: 100%

Показывает, что запрет по умолчанию работает для неавторизованных и невалидных запросов.

P95 security validation latency

Target: < 30 ms

Контроли безопасности живут на горячем пути запроса — они не должны заметно бить по отклику для пользователя и целям уровня обслуживания () программного интерфейса.

Critical API vuln remediation time

Target: < 24 hours

Оценивает скорость устранения найденных рисков в публичной поверхности.

Replay/abuse incident MTTR

Target: < 60 minutes

Чем быстрее локализован сценарий злоупотребления, тем меньше финансовый и репутационный ущерб.

Roadmap внедрения

1

Фаза 1 (0-30 дней)

Фокус: Инвентаризация поверхности API

Результат: Каталог API, классификация критичности, для каждого публичного контракта.

2

Фаза 2 (30-60 дней)

Фокус: Базовые обязательные контроли

Результат: Единые политики аутентификации и авторизации (AuthN/AuthZ), и на шлюзе и границе сети.

3

Фаза 3 (60-90 дней)

Фокус: Устойчивость к злоупотреблениям

Результат: , защита от ботов, корреляция телеметрии и автоматизация потоков обнаружения.

4

Фаза 4 (90+ дней)

Фокус: Операционная зрелость

Результат: Регулярные по сценариям атак, разбор метрик и постоянный бэклог укрепления защиты.

Типичные антипаттерны

Полагаться на защиту периметра и не проверять права доступа внутри сервиса: один пробитый периметр — и весь внутренний трафик считается доверенным.

Смешивать пользовательские и машинные токены без явной модели привилегий — машинный токен с правами человека обходит половину контролей.

Разрешать повторные попытки (retry) в пишущих эндпоинтах без защиты от повторного воспроизведения и ключей идемпотентности: один ретрай — и платёж проходит дважды.

Логировать тело запроса целиком в проде — лог становится самой длинной утечкой чувствительных данных.

Отключать строгую проверку схемы ради «быстрого релиза»: дыру в валидации находят раньше, чем успевают вернуть проверку.

References

Связанные главы

  • OWASP Top 10 в контексте System Design - Даёт карту классов уязвимостей; на поверхности программного интерфейса они оборачиваются конкретными атаками — BOLA, массовым назначением полей (mass assignment) и обходом аутентификации.
  • Идентификация, аутентификация и авторизация - Закладывает контур управления доступом (IAM); пока его нет, контроли безопасности API держатся на полумерах и легко обходятся.
  • Zero Trust: архитектура нулевого доверия - Поднимает те же принципы на уровень архитектуры: проверять каждый запрос и решать о доступе по контексту, а не по факту нахождения внутри сети.
  • Secrets Management Patterns - Покрывает безопасное управление API-ключами, и токенами в среде выполнения и CI/CD.
  • Data Governance & Compliance - Связана с политиками обработки и требованиями аудита для API, работающих с чувствительными данными.

Чтобы отмечать прохождение, включи трекинг в Настройки