← Все статьи

Как защитить REST API: практический чек-лист

Burncode Team 4 минуты чтения

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

Аутентификация: кто отправляет запрос

Каждый запрос к защищённому эндпоинту должен надёжно идентифицировать отправителя. Распространённые и проверенные подходы — API-ключи для взаимодействия между сервисами и аутентификация на основе токенов (например, OAuth 2.0 или JWT) для пользовательских приложений. Конкретный механизм важен меньше, чем базовые вещи: у токенов должен быть срок действия, передавать их следует только по зашифрованным соединениям, и они никогда не должны попадать в URL — оттуда они с гораздо большей вероятностью окажутся в каком-нибудь незащищённом логе.

Авторизация: что отправителю разрешено

Аутентификация отвечает на вопрос «кто вы?». Авторизация — на вопрос «что вам разрешено?», и это отдельная проверка, которая должна выполняться при каждом запросе, а не однократно при входе. Очень распространённая и опасная ошибка: API правильно проверяет, что у запроса есть действительный токен, но не проверяет, принадлежит ли запрошенный ресурс именно этому пользователю. Так один пользователь получает возможность просматривать или изменять чужие данные, просто подставив в запрос другой ID. Это одна из разновидностей нарушения контроля доступа — проблемы, которую при реальных аудитах безопасности находят чаще всего.

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

Без ограничения частоты запросов (rate limiting) один-единственный клиент — злонамеренный или просто неправильно настроенный — может засыпать ваш API запросами: чтобы подобрать перебором, например, пароль через эндпоинт входа или просто чтобы перегрузить инфраструктуру. На практике это означает разумные лимиты запросов на пользователя или на API-ключ, понятный ответ клиенту, который упёрся в лимит, и более строгие ограничения для чувствительных эндпоинтов — входа и сброса пароля, — чем для обычных запросов на чтение.

Валидация входных данных: не доверяйте ничему, что приходит извне

Каждое поле каждого запроса нужно проверять на соответствие ожиданиям — тип, длину, формат, допустимый диапазон — прежде чем использовать его где-либо в логике приложения. Тот же принцип защищает от SQL-инъекций, но применим он гораздо шире: некорректные или неожиданные входные данные стоят за значительной долей реальных уязвимостей приложений, и далеко не только в запросах к базе данных.

Защита передачи данных: шифруйте всё, без исключений

Все запросы и ответы должны передаваться по HTTPS, без какой-либо возможности откатиться на незашифрованное соединение, даже для эндпоинтов, которые кажутся малорискованными. Современные инструменты (например, Let's Encrypt) позволяют настроить это практически бесплатно, так что оправданий пропустить этот пункт где-либо в API почти не бывает.

Продуманные сообщения об ошибках

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

Логирование и мониторинг

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

Чек-лист, по которому стоит проверить свой API

  • Требует ли каждый эндпоинт аутентификации, кроме тех, что намеренно сделаны публичными?
  • Проверяет ли каждый запрос, что пользователь имеет право на доступ именно к этому ресурсу, а не просто вошёл в систему?
  • Настроено ли ограничение частоты запросов, особенно для входа, сброса пароля и других чувствительных эндпоинтов?
  • Проверяются ли все входные данные перед использованием, а не только те, что выглядели явно рискованными?
  • Используется ли HTTPS везде, без исключений?
  • Не раскрывают ли ответы с ошибками в продакшене внутренние детали реализации?
  • Достаточно ли логов, чтобы потом действительно расследовать инцидент?

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