OWASP выпустил отдельный список угроз для API в 2019 году и обновил его в 2023-м. Это важно: уязвимости API отличаются от уязвимостей обычных веб-приложений. Можно закрыть всё из классического OWASP Top 10 и при этом оставить API полностью открытым.
Почему API — отдельная история
API стали основой всего: мобильные приложения, SPA, сторонние интеграции, IoT-устройства — всё работает через API. Если раньше уязвимость позволяла взломать один сайт, то через API можно добраться до данных миллионов пользователей за один запрос.
Разбираем все десять пунктов OWASP API Security Top 10 по порядку — с примерами и конкретными действиями.
API1: Сломанная авторизация на уровне объектов (BOLA)
Самая распространённая уязвимость API. Пользователь делает запрос к объекту, который ему не принадлежит, и получает его.
Пример: ты видишь свой заказ по адресу /api/orders/12345. Меняешь 12345 на 12346 — и видишь чужой заказ. Сервер проверяет, авторизован ли пользователь вообще, но не проверяет, имеет ли он доступ к конкретному объекту.
Звучит как очевидная ошибка, но встречается в каждом втором API. В 2021 году через похожую уязвимость утекли данные 700 миллионов пользователей LinkedIn.
Как защититься:
- Всегда проверяй права доступа на уровне каждого объекта, а не только на уровне эндпоинта
- Используй непредсказуемые идентификаторы — UUID вместо последовательных чисел
- Пиши тесты, которые специально пытаются обратиться к чужим объектам
API2: Сломанная аутентификация
Всё, что связано с тем, как API удостоверяется, что запрос пришёл именно от тебя. Слабые механизмы: токены не истекают, можно перебирать пароли без ограничений, токены передаются в URL и оседают в логах.
Реальный кейс: у API нет rate limiting на эндпоинте /api/login. Злоумышленник запускает перебор — тысячи запросов в секунду, ни одна защита не срабатывает. За несколько часов он получает доступ к аккаунтам с простыми паролями.
Частая ошибка — передавать токен в query-параметре: /api/data?token=abc123. Этот URL попадёт в логи сервера, браузерную историю, Referer-заголовок при переходе на другой сайт. Токен скомпрометирован.
Что делать:
- Токены — только в заголовке
Authorization, никогда в URL
- Срок жизни access-токена — не больше 15–60 минут
- Rate limiting на все эндпоинты аутентификации
- Блокировка после N неудачных попыток
- Для критичных операций — многофакторная аутентификация
API3: Сломанная авторизация на уровне свойств объекта
Пользователь имеет доступ к объекту, но не ко всем его полям — а API возвращает их всё равно.
Классика: /api/users/me возвращает не только имя и email, но и is_admin: false, internal_score: 72, password_hash: $2b$10$.... Фронтенд показывает только нужные поля, но данные в ответе есть — достаточно открыть DevTools.
Обратная проблема — Mass Assignment: пользователь передаёт в PUT-запросе поля, которые не должен менять, и сервер их принимает. Отправил {"name": "Иван", "role": "admin"} — и стал администратором.
Защита:
- Явно описывай, какие поля входят в ответ (whitelist, не blacklist)
- Используй DTO и сериализаторы, которые фильтруют вывод
- На входе принимай только те поля, которые пользователь вправе менять
- Никогда не передавай ORM-объект напрямую в ответ
API4: Неограниченное потребление ресурсов
API без ограничений — приглашение, которым кто-то обязательно злоупотребит. Злоумышленник делает тысячи запросов, запрашивает огромные объёмы данных, запускает дорогие операции.
Пример: эндпоинт генерации отчётов работает 10 секунд и загружает базу данных. Без ограничений один пользователь запускает 100 параллельных запросов — сервер ложится. Или /api/users?page=1&limit=10000 — и API честно возвращает 10 000 записей одним запросом.
Что ограничивать:
- Максимальный размер тела запроса
- Количество записей в ответе (максимальный
limit)
- Rate limiting по IP и по токену
- Таймауты на выполнение запросов
- Максимальное количество параллельных соединений с одного источника
API5: Сломанная авторизация на уровне функций
Обычный пользователь вызывает административный эндпоинт, просто угадав URL.
Типичная картина: в мобильном приложении есть /api/admin/users — но приложение его не показывает рядовым пользователям. Сервер, однако, проверяет только наличие токена, а не роль. Находчивый человек пробует URL — и получает список всех пользователей.
HTTP-методы тоже в зоне риска. API разрешает GET /api/orders/123, но не проверяет DELETE /api/orders/123 — потому что «кто додумается».
Как быть:
- Проверяй разрешения на каждый эндпоинт, а не только на «чувствительные»
- Используй middleware авторизации, который нельзя случайно пропустить
- Разделяй пространства имён: отдельный роутер или сервис для административных функций
- Проводи аудит всех доступных эндпоинтов с точки зрения разных ролей
API6: Неограниченный доступ к чувствительным бизнес-процессам
Некоторые операции опасны при злоупотреблении — даже если технически всё реализовано правильно. Создание аккаунтов, бронирование мест, применение промокодов, выставление инвойсов.
Известная история: сервис продажи билетов не ограничивал количество операций бронирования в единицу времени. Боты бронировали все места за секунды, потом перепродавали. Технически — никакой уязвимости. По факту — злоупотребление бизнес-логикой.
Защита здесь — не только технические меры:
- Капча или другие верификаторы на критичных операциях
- Анализ поведения: один IP делает 50 бронирований за минуту — подозрительно
- Ограничения на уровне бизнес-логики (один промокод = один аккаунт + одна платёжная карта)
- Device fingerprinting для выявления автоматизации
API7: Server Side Request Forgery (SSRF)
API принимает URL от пользователя и делает запрос по этому адресу. Всё бы ничего, но что если пользователь передаст http://169.254.169.254/latest/meta-data/ — адрес метаданных AWS? Или http://internal-service.company.local/admin?
SSRF позволяет использовать сервер как прокси для атаки на внутреннюю инфраструктуру. Именно через SSRF в 2019 году взломали Capital One и получили данные 100 миллионов клиентов.
Типичные точки входа: загрузка изображений по URL, предпросмотр ссылок, вебхуки, импорт данных из внешних источников.
Как закрыть:
- Никогда не делай запрос к URL от пользователя без валидации
- Whitelist разрешённых доменов — только они
- Блокируй запросы к приватным IP-диапазонам: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16
- Выполняй внешние запросы из изолированной сети без доступа к внутренним сервисам
API8: Неправильная конфигурация безопасности
Самое обидное место в списке. Код написан правильно, логика верная — но сервер настроен как попало.
Что сюда входит:
- Включённые дебаг-режимы в продакшене: стек-трейсы в ответах API — подарок для атакующего
- CORS настроен на
* для всех эндпоинтов, включая чувствительные
- Устаревшие версии TLS (1.0, 1.1) всё ещё поддерживаются
- Заголовки безопасности отсутствуют: нет
X-Content-Type-Options, Strict-Transport-Security
- Swagger-документация открыта в продакшене без авторизации
Банальный пример: сервер возвращает в заголовке Server: nginx/1.14.0. Атакующий знает версию, идёт смотреть CVE для неё — и находит.
Чеклист:
- Убери все дефолтные учётные данные
- Отключи всё лишнее: методы, эндпоинты, сервисы
- Настрой CORS точечно, а не глобально
- Скрой технические детали в ответах об ошибках
- Автоматизируй проверку конфигурации в CI/CD
API9: Неправильное управление инвентарём
У растущей компании появляются десятки API: версии, внутренние, партнёрские, тестовые. Кто-то забыл задокументировать эндпоинт, кто-то не выключил тестовый сервер, кто-то оставил v1 работать рядом с v3.
Старые версии API — клад для атакующих. В них меньше защиты, их хуже проверяют, их никто не патчит. Находишь /api/v1/users рядом с /api/v3/users — первый может быть без авторизации вообще.
Типичная история: компания перешла на v2, но v1 не выключила — «вдруг что-то сломается». Прошёл год. О v1 все забыли. В нём всё ещё нет проверки прав.
Что делать:
- Веди реестр всех API: версии, среды, владелец, дата создания
- Устанавливай политику конца жизни версий и соблюдай её
- Используй API Gateway — единая точка входа, которую легко контролировать
- В тестовых средах — только тестовые данные, никогда реальные
API10: Небезопасное потребление сторонних API
Парадокс: ты тщательно защищаешь свой API, но слепо доверяешь данным, которые приходят от внешних сервисов. А что если те данные скомпрометированы?
Если приложение получает адрес от стороннего геосервиса и подставляет его в SQL-запрос без проверки — это SQL-инъекция через доверенный источник. Если берёшь HTML из внешнего API и рендеришь напрямую — XSS.
Атаки на цепочку поставок именно так и работают. Компрометируется не твой сервис, а тот, которому ты доверяешь.
Правила:
- Валидируй данные из внешних API так же строго, как пользовательский ввод
- Взаимодействуй со сторонними сервисами только по HTTPS с проверкой сертификата
- Не расширяй привилегии на основе данных от третьей стороны без дополнительной проверки
- Следи за состоянием зависимостей и используемых внешних сервисов
Как применить это на практике
Десять пунктов могут казаться большим объёмом, но начать стоит с самого частого:
- Добавь проверку прав на уровне каждого объекта — это закрывает API1 и API5
- Включи rate limiting на аутентификацию — API2
- Используй сериализаторы с явным whitelist полей — API3
- Настрой глобальные лимиты на размер запросов и пагинацию — API4
- Проведи аудит конфигурации сервера по чеклисту — API8
Если разрабатываешь API с нуля или рефакторишь существующий, посмотри на инструменты автоматической проверки: OWASP ZAP, 42Crunch, Spectral умеют анализировать OpenAPI-спецификации и находить потенциальные проблемы ещё до деплоя.
В REEXY при разработке API для клиентских проектов — будь то интеграция сервисов от 1 500 ₽ или полноценный бэкенд интернет-магазина — проверки авторизации и rate limiting закладываются на этапе проектирования, а не добавляются потом. Это дешевле и надёжнее.
Безопасность API — не разовая задача. Угрозы меняются, OWASP обновляет список, появляются новые паттерны атак. Самое практичное действие прямо сейчас: взять свой API и пройтись по каждому пункту этого списка с вопросом «а у нас это проверяется?». Ответ часто удивляет.