Направление К4 · pillar-материал

Безопасные API: REST, GraphQL, аутентификация и OWASP API Security Top 10

API — невидимая часть веб-приложения, через которую проходит основной трафик данных между сервисами, мобильным клиентом, сторонними партнёрами. В 2026 году API стали основной целью атак: на каждый уязвимый веб-эндпоинт приходится 3–5 уязвимых API. Этот материал — практическое руководство по защите REST и GraphQL API для CISO и тимлидов разработки: разбор OWASP API Security Top 10, выбор аутентификации, rate-limiting, secrets management, специфика GraphQL.

Почему API — отдельный класс угроз

Веб-приложение традиционно атакуется через UI: пользователь заполняет форму, нажимает кнопку. API атакуют напрямую: автоматизированные скрипты вызывают эндпоинты в нужном порядке, обходя любые фронтенд-валидации. Это создаёт три специфики API-безопасности:

  • Объём атакуемой поверхности. Один публичный сайт = 30–50 страниц. Тот же сайт через API = 200–500 эндпоинтов. Сложнее покрыть пентестом и сканерами.
  • Логика на клиенте. Старые UI-приложения выполняли валидацию на сервере. Современные SPA часто валидируют на клиенте и доверяют запросам — это путь к BOLA, IDOR, BFLA.
  • Скрытность. Атаки на API легко маскируются под легитимный трафик мобильного приложения, сложнее выявляются мониторингом, дольше остаются незамеченными.

OWASP API Security Top 10

OWASP API Security Top 10:2023 — обязательный документ для команды разработки. Каждая из 10 категорий — типовая ошибка и способ её закрытия.

API1: Broken Object Level Authorization (BOLA)

Эндпоинт GET /api/orders/12345 возвращает заказ без проверки, принадлежит ли он текущему пользователю. Простейшая и самая распространённая уязвимость. Решение — проверка владельца на каждый запрос. Удобный паттерн: ORM-фильтр, который автоматически добавляет WHERE user_id = ? ко всем выборкам, или middleware, который верифицирует доступ до вызова обработчика.

API2: Broken Authentication

Слабая аутентификация: предсказуемые токены, отсутствие rate-limiting на login, использование «none» в JWT-алгоритме, утечка токенов в URL. Решение — стандартные библиотеки (oauthlib, jose, passport), никогда не реализовывать аутентификацию с нуля, использовать sliding-токены вместо «вечных» сессий, ротация секретов раз в 90 дней.

API3: Broken Object Property Level Authorization (BOPLA)

Эндпоинт возвращает или принимает поля, к которым у пользователя нет прав. Например, PATCH /api/users/me с телом {"role": "admin"} — а сервер обновляет поле role, потому что не фильтрует входной DTO. Решение — явные allowlist полей в DTO (Pydantic, class-validator, marshmallow), отдельные модели для чтения и записи, мнимая иммутабельность критичных полей.

API4: Unrestricted Resource Consumption

Эндпоинт без rate-limiting или с возможностью передать запрос на миллион записей. Атакующий исчерпывает CPU/RAM/БД сервера. Решение — rate-limiting по IP/пользователю/API-ключу, pagination с hard cap (например, не более 100 записей за запрос), таймауты на долгие операции, async-обработка тяжёлых запросов через очередь.

API5: Broken Function Level Authorization (BFLA)

Обычный пользователь может вызвать административный эндпоинт. Часто из-за «обратной авторизации» — скрытие в UI вместо запрета на бэкенде. Решение — серверная проверка ролей на каждом административном эндпоинте, использование декораторов @require_role('admin'), отдельные namespace для административного и публичного API.

API6: Unrestricted Access to Sensitive Business Flows

Чувствительные бизнес-сценарии (бронирование, чекаут, отзывы, регистрация) без анти-автоматизации. Атакующий запускает скрипт, который выкупает все билеты, накручивает рейтинг, регистрирует тысячи фейковых аккаунтов. Решение — bot management, поведенческие лимиты (новый аккаунт не может купить больше N товаров в день), CAPTCHA на критичных переходах, выявление аномалий по device fingerprint.

API7: Server-Side Request Forgery (SSRF)

Бэкенд принимает URL от пользователя и делает к нему запрос. Атакующий передаёт http://169.254.169.254/latest/meta-data/ (AWS IMDS) и получает токены доступа к инфраструктуре. Решение — белый список разрешённых доменов, резолюция URL в IP до запроса, блокировка частных диапазонов, IMDS v2 в AWS (требует токен), отдельный proxy-сервис для исходящих запросов.

API8: Security Misconfiguration

DEBUG=true в production, дефолтные пароли, открытый management-эндпоинт (Spring Actuator, Django admin), избыточные данные в ответах (полный stack trace), CORS-политика с Access-Control-Allow-Origin: *. Решение — hardening базовых образов, security audit конфигурации в CI/CD, минимизация раскрытия (общие сообщения об ошибках, скрытие версий ПО), отдельная инфраструктурная команда с чек-листом.

API9: Improper Inventory Management

Старые версии API, неучтённые тестовые эндпоинты, забытые beta-системы — все остаются доступны через интернет. Решение — обязательная регистрация всех эндпоинтов (OpenAPI/AsyncAPI спецификация как single source of truth), регулярная инвентаризация атакуемой поверхности (например, через GAU, subfinder), процесс «убери лишнее» при выводе из эксплуатации.

API10: Unsafe Consumption of APIs

Ваш сервис доверяет внешнему API больше, чем нужно: использует данные без валидации, следует редиректам без проверки, обрабатывает большие ответы без лимита. Решение — валидация входа независимо от источника, явные таймауты и max body size, отдельный circuit breaker для каждого внешнего API.

Полный текст и регулярные обновления — на owasp.org/API-Security.

Аутентификация API: выбор метода

СценарийМетодПочему
Публичный API для сторонних разработчиковOAuth2 (Authorization Code + PKCE)Стандарт индустрии, разделение прав через scopes, безопасный обмен токенами
SPA + backend (тот же домен)HttpOnly cookie с session ID + CSRF-токенБезопаснее JWT в localStorage, защищён от XSS-кражи
Мобильный клиент → backendJWT короткой жизни + refresh-токен в защищённом хранилищеНе нужно слать cookies, токены отзываются через ротацию
Service-to-service внутри сетиmTLS или подписанные запросы (HMAC, AWS Signature v4)Нет «человеческой» аутентификации, нужна криптографическая
Простой backend-to-backend, доверенный партнёрAPI-key + IP whitelist + rate-limitМинимум сложности там, где нет публичного риска
Машинная аутентификация между сервисамиOAuth2 Client CredentialsСтандартизация и аудит на уровне Identity Provider

JWT: типичные ошибки

  • Алгоритм «none». Никогда не принимайте JWT с алгоритмом «none». Жёстко фиксируйте список разрешённых алгоритмов (обычно RS256 или HS256).
  • Слабый секрет. HS256 со словарным секретом — пол-дня для атаки полным перебором.
  • Долгоживущий токен. Access-токен на 30 дней — это утечка на 30 дней. Лимит 15–60 минут плюс refresh.
  • Отсутствие ревокации. JWT по дизайну неотзываем. Если нужно отзывать (например, при увольнении сотрудника) — добавляйте серверный allowlist токенов или используйте короткий срок жизни + refresh.

Авторизация: RBAC, ABAC, ReBAC

После аутентификации (кто пользователь) нужна авторизация (что ему можно).

  • RBAC (Role-Based Access Control). Простая ролевая модель: admin/manager/user. Подходит для большинства приложений с понятной иерархией.
  • ABAC (Attribute-Based Access Control). Решение на основе атрибутов: «пользователь может редактировать заказ, если он его автор И статус «черновик» И сегодня будний день». Гибкая, сложная в поддержке.
  • ReBAC (Relationship-Based Access Control). Через граф связей: «пользователь имеет доступ к проекту, если состоит в команде, которой принадлежит проект». Популяризирована Zanzibar (Google), удобна для соц-сетей, документных систем.

Для большинства коммерческих SaaS RBAC + 1–2 уровня уточнения (например, ownership-check) даёт нужный баланс. Открытые движки: Casbin, Cerbos, OpenFGA (модель Zanzibar), Oso.

Rate-limiting и quotas на уровне API

Минимальные уровни лимитов:

  • На уровне сети (CDN/WAF) — глобальные лимиты по IP, например 1000 запросов/мин.
  • На уровне API Gateway — лимиты по API-ключу/токену (например, 100 запросов/секунду, 10 000/час).
  • На уровне приложения — endpoint-specific (login 10/мин, password reset 3/час, payment 30/мин).
  • Бизнес-quotas — суточные, недельные, месячные (например, free-план: 1000 запросов/день).

Реализация: Redis с sliding-window или leaky bucket. Готовые библиотеки: express-rate-limit, slowapi, django-ratelimit. Для API Gateway — встроенные плагины в Kong, KrakenD, APISIX.

Secrets management

Production-приложение не должно содержать секретов в коде, переменных окружения хост-машины, файлах конфигурации в репозитории. Уровни решений:

  • HashiCorp Vault — open-source, ставится локально или в облаке, поддерживает dynamic secrets (БД-учётки на 1 час), отзыв по событию, audit log.
  • OpenBao — форк Vault от Linux Foundation после изменения лицензии. Для импортозамещения и отсутствия санкционных рисков — предпочтительнее в РФ.
  • Облачные secret managers. Yandex Lockbox, SberCloud Secrets Manager, AWS Secrets Manager — если уже используете соответствующее облако.
  • SOPS — для шифрования файлов с секретами в git (когда нужен GitOps-подход).

Базовые правила: автоматическая ротация секретов (раз в 30–90 дней), отдельные секреты для каждого окружения, минимальные права (приложение читает только свои секреты, не всё пространство), audit log каждого обращения, интеграция с CI/CD (не вытаскивать секреты руками).

API Gateway: когда нужен

API Gateway — отдельный слой между клиентом и микросервисами, который принимает все запросы и решает кросс-функциональные задачи.

  • Kong — самый популярный open-source Gateway, плагинная архитектура, активное сообщество.
  • Apache APISIX — Cloud Native Gateway, оптимизирован под Kubernetes, под лицензией Apache 2.0.
  • KrakenD — высокопроизводительный, без хранилища состояния, идеален для агрегации множества backend-сервисов.
  • Traefik Enterprise / Tyk — коммерческие альтернативы с расширенной аналитикой.

Gateway оправдан, когда у вас 3+ микросервиса или планируется публичный API с тарифными планами. Для одного монолита с REST-эндпоинтами — избыточная сложность.

GraphQL-специфика

GraphQL даёт клиенту больше выразительности, но и добавляет угрозы:

  • Query depth. Лимит вложенности (5–10 уровней). Без него запрос «friends.friends.friends...» уронит БД.
  • Query complexity. Анализ стоимости запроса до выполнения. Библиотеки: graphql-cost-analysis, graphql-validation-complexity.
  • Batching. Отключайте для критичных операций (login, password reset) — иначе обходится rate-limit одним запросом с 1000 мутаций.
  • Introspection. В production отключайте — иначе атакующий видит всю схему.
  • N+1. Не безопасность, но проблема производительности. DataLoader — стандартное решение.

Кейс: рефакторинг небезопасного REST API

B2B-сервис документооборота. Команда из 6 разработчиков, монолит на Django + DRF, ~120 эндпоинтов. За год развития накопились типовые проблемы: BOLA в каждом втором эндпоинте, токены без срока жизни, логирование критичных операций отсутствует, секреты в .env прямо на сервере. На pentest — 4 Critical, 11 High.

План рефакторинга на 3 месяца:

  1. Месяц 1. Внедрение единого middleware с проверкой ownership-уровня (закрывает BOLA по всем эндпоинтам сразу). Ротация всех боевых токенов. Перевод секретов в Vault.
  2. Месяц 2. Внедрение API Gateway (Kong) с централизованным rate-limiting и логированием. Audit log изменений критичных данных.
  3. Месяц 3. Threat modeling, переписывание авторизации через Casbin (RBAC + ownership), отключение интроспекции в production, security headers через Gateway.

Re-test через 4 месяца после старта работ: 0 Critical, 2 High (новые, незакрытые сценарии в свежем модуле), 1 Medium. Дополнительный эффект — снижение времени дебага продакшен-инцидентов с дней до часов благодаря централизованному audit log.

Сравнение решений: API Gateway, secrets manager, API monitoring

Зрелая защита API строится из трёх ортогональных классов решений: Gateway (контроль входящего трафика), secrets manager (управление ключами и токенами), API monitoring (детект аномалий).

КлассРешенияКогда выбирать
API GatewayKong, Apache APISIX, KrakenD, Tyk, Traefik EnterpriseKong — стандарт, плагинная архитектура; APISIX — для Kubernetes-native; KrakenD — для агрегации многих backend-ов; Tyk — коммерческая аналитика
Secrets managerHashiCorp Vault, OpenBao, Yandex Lockbox, AWS Secrets Manager, DopplerVault — on-prem стандарт; OpenBao — open-source-форк под импортозамещение; Lockbox — для проектов на Yandex Cloud; Doppler — managed cloud для небольших команд
API security monitoringWallarm API Security, Salt Security (зарубежный), Noname Security, custom WAF+SIEMWallarm — единый российский стек, оптимально для среднего бизнеса; custom — для команд с зрелой ИБ-практикой
OAuth2 / OIDC серверKeycloak, Ory Hydra, Authentik, Auth0 (зарубежный)Keycloak — стандарт; Ory Hydra — для headless-сценариев; Authentik — современный UX, активная разработка

Расширенный кейс: API-first SaaS с массовым BOLA

B2B-SaaS аналитики «Заказчик Г» — платформа для маркетинговых агентств, ~140 клиентских кабинетов, ~2300 пользователей суммарно. Архитектура: Python+FastAPI, PostgreSQL, REST API (~180 эндпоинтов), React SPA. На pentest (формат grey-box, 4 недели) обнаружили массовый BOLA: 73 из 180 эндпоинтов позволяли менять project_id в URL и получать данные чужих клиентов. Эта одна цепочка эксплуатации давала полный доступ к 1.4 млн отчётов всех клиентов.

План восстановления (10 недель):

  1. Week 1. Экстренное rate-limit на критичные эндпоинты (50 req/мин/учётка), мониторинг через ELK + правила корреляции для детекта аномальных паттернов сканирования.
  2. Weeks 2–4. Внедрение единого ownership-middleware: при каждом запросе с project_id в URL автоматическая проверка «принадлежит ли этот project текущему workspace пользователя». Закрыло BOLA по всем 73 эндпоинтам сразу.
  3. Weeks 5–6. Перевод секретов из .env в HashiCorp Vault, ротация всех боевых ключей (БД, S3, SMTP, токены интеграций), audit log обращений к Vault.
  4. Weeks 7–8. Внедрение Kong как API Gateway, централизованный rate-limit, логирование в Wazuh, OAuth2 для публичного API партнёрам.
  5. Weeks 9–10. Threat modeling нового модуля «общие папки», переписывание авторизации через Casbin (RBAC + ABAC + ownership), интеграция SAST (Semgrep) и SCA (Snyk) в CI.

Re-test через 12 недель: 0 Critical, 1 High (новый эндпоинт массовой выгрузки требовал отдельной rate-limit логики), 3 Medium. Стоимость проекта — 4.8 млн ₽ + 80 тыс. ₽/мес постоянных расходов на Vault + Kong + monitoring. Сравнительная стоимость потенциальной утечки 1.4 млн отчётов — ~50 млн ₽ штрафа РКН + полная потеря enterprise-клиентов.

Стандарты и регуляторы

Связанные материалы

FAQ о безопасности API

JWT, OAuth2, API-ключ, mTLS — что выбрать для авторизации API?

Зависит от модели: публичный API для сторонних разработчиков — OAuth2 с access/refresh-токенами. Внутренние сервисные вызовы (service-to-service) — mTLS или подписанные запросы (HMAC). API мобильного клиента вашего же приложения — JWT с коротким сроком жизни + refresh-токен в HttpOnly cookie. Простой backend-to-backend без публичного выхода — API-ключ с rate-limit и whitelist IP. Главное правило: один механизм, реализованный правильно, лучше трёх «полу-правильно».

Что такое BOLA и почему это самая опасная уязвимость API?

BOLA (Broken Object Level Authorization) — №1 в OWASP API Security Top 10. Атакующий меняет ID объекта в URL (например, GET /api/invoices/12345 → 12346) и получает чужие данные, потому что бэкенд проверяет только аутентификацию (пользователь залогинен), но не авторизацию (имеет ли он право на этот объект). Эта уязвимость встречается на 70-80% pentest и часто даёт массовый доступ к данным всех пользователей. Решение — обязательная проверка владельца объекта в каждом обработчике запроса, желательно через единый middleware или ORM-фильтры.

Как защитить API от SSRF, когда сервер должен делать внешние запросы (webhook-и, импорт по URL)?

Базовый подход: белый список доменов, на которые разрешены исходящие запросы. Если белый список невозможен (например, webhook-и партнёров) — резолвить URL в IP до запроса и блокировать частные диапазоны (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.169.254 — AWS IMDS, ::1). Использовать отдельный сервис-прокси с минимальными правами, через который проходят все внешние вызовы. Включить IMDS v2 в AWS (требует токен в запросе). Логировать все исходящие запросы для расследования инцидентов.

Где хранить секреты для production: переменные окружения, файлы, Vault?

Переменные окружения — минимальный уровень, проще чем хранить пароли в коде, но всё ещё попадает в логи процессов, дампы памяти, кор-файлы. Файлы (.env) — не лучше переменных и опасны при случайных git-коммитах. Production-уровень — централизованный secrets manager: HashiCorp Vault (open-source, ставится локально), OpenBao (форк Vault от LF, для импортозамещения), AWS Secrets Manager / Yandex Lockbox / SberCloud Secrets Manager. Базовые принципы: автоматическая ротация (раз в 30-90 дней), audit log каждого обращения, минимальные права (приложение читает только свои секреты), отдельные секреты для каждого окружения.

Нужен ли отдельный API Gateway или можно обойтись nginx и кодом?

Для нескольких сервисов с похожими требованиями (аутентификация, rate-limiting, логирование, CORS) API Gateway сильно упрощает жизнь — Kong, KrakenD, Apache APISIX. Он берёт на себя кросс-функциональные задачи, освобождая код приложения. Если у вас один монолит — добавлять Gateway избыточно, достаточно настроить nginx и middleware. Если 5+ сервисов / микросервисов — Gateway уже окупается. Если планируете публичный API для партнёров с тарифными планами и квотами — Gateway почти обязателен.

Чем GraphQL опаснее REST с точки зрения безопасности?

GraphQL даёт клиенту больше контроля над запросом: можно вложенно запрашивать связанные объекты, что создаёт три новых класса угроз. Первый — query depth attack: вложенность поля «друзья друзей друзей» взрывает БД. Решение — depth limit (5-10 уровней). Второй — query complexity attack: запрос, который при разворачивании создаёт миллионы операций. Решение — cost analysis, лимит на сложность. Третий — batching attack: множество вложенных мутаций в одном запросе, обходящих rate-limit. Решение — отключать batching для критичных операций (login, password reset, payment). Плюс отдельная угроза — введение в production включенного introspection (показывает всю схему злоумышленнику). В production introspection отключают.

Какие минимальные требования к логированию API?

Каждый запрос: timestamp, user_id (если есть), API-ключ или клиентский ID, метод, путь, IP, User-Agent, статус ответа, длительность. Тело запроса — не логируйте полностью, маскируйте чувствительные поля (пароли, токены, номера карт, серии паспортов). Изменения данных — отдельный audit-log с before/after. Аутентификация — успешные и неудачные попытки. Административные действия — отдельным потоком с долгим хранением. Минимальное retention для compliance — 6 месяцев, для 152-ФЗ практичнее год. Защита логов от модификации — обязательна (write-once хранилище или SIEM с контролем целостности).

Что хуже — IDOR или BOLA, или это одно и то же?

BOLA (Broken Object Level Authorization) — это формальное название из OWASP API Security Top 10 для уязвимости, которую раньше называли IDOR (Insecure Direct Object Reference). По сути — то же самое: атакующий меняет идентификатор объекта в запросе и получает чужие данные. Разница в нюансе: IDOR — общий термин для веб-приложений и API, BOLA — точное название для API. В отчётах pentest 2024+ корректнее использовать BOLA. Опаснее, чем XSS или SQLi, потому что эксплуатируется в одну строку, без подготовки payload-а — атакующему достаточно сменить число в URL.

Нужно ли подписывать webhook-и партнёрам? Как?

Обязательно подписывать каждый исходящий webhook — иначе подделать запрос от вашего имени тривиально. Стандарт: HMAC-SHA256 от тела запроса + timestamp + nonce, в заголовке X-Signature. Партнёр на своей стороне проверяет подпись и отклоняет timestamp старше 5 минут (защита от replay-атак). Дополнительно: rotation секретов раз в 90 дней, отдельный секрет для каждого партнёра, отдельный секрет для каждого окружения. Эталонные реализации — у Stripe (Stripe-Signature) и GitHub (X-Hub-Signature-256), их документация — хороший шаблон.

Как защититься от reverse engineering мобильного API?

Полностью невозможно — любой клиент, исполняемый на устройстве пользователя, можно разобрать. Реалистичная цель — повысить стоимость reverse engineering: certificate pinning (приложение принимает только конкретный сертификат сервера), obfuscation бинарного кода (R8/ProGuard для Android, Hermes для React Native), детект Frida/Magisk/jailbreak с soft-block, перенос критичной логики на сервер (расчёт цены — на бэкенде, не на клиенте), временные токены с коротким TTL, anti-replay механизмы. Главное правило: не доверять клиенту — все важные проверки делать на бэкенде, даже если они есть в коде клиента.

Обсудить аудит API Бесплатная 30-минутная встреча: текущее состояние API, риски, ориентировочный объём работ.