Как защитить REST API: практический чек-лист
API нередко оказывается самой открытой частью современного приложения: он по определению создан для того, чтобы принимать запросы извне, а значит, это и самый прямой путь злоумышленника к вашим данным и бизнес-логике. Надёжная защита API — не одна функция, а целый перечень отдельных задач, и каждую из них стоит проработать вдумчиво.
Аутентификация: кто отправляет запрос
Каждый запрос к защищённому эндпоинту должен надёжно идентифицировать отправителя. Распространённые и проверенные подходы — API-ключи для взаимодействия между сервисами и аутентификация на основе токенов (например, OAuth 2.0 или JWT) для пользовательских приложений. Конкретный механизм важен меньше, чем базовые вещи: у токенов должен быть срок действия, передавать их следует только по зашифрованным соединениям, и они никогда не должны попадать в URL — оттуда они с гораздо большей вероятностью окажутся в каком-нибудь незащищённом логе.
Авторизация: что отправителю разрешено
Аутентификация отвечает на вопрос «кто вы?». Авторизация — на вопрос «что вам разрешено?», и это отдельная проверка, которая должна выполняться при каждом запросе, а не однократно при входе. Очень распространённая и опасная ошибка: API правильно проверяет, что у запроса есть действительный токен, но не проверяет, принадлежит ли запрошенный ресурс именно этому пользователю. Так один пользователь получает возможность просматривать или изменять чужие данные, просто подставив в запрос другой ID. Это одна из разновидностей нарушения контроля доступа — проблемы, которую при реальных аудитах безопасности находят чаще всего.
Ограничение частоты запросов: защита от злоупотреблений и перегрузки
Без ограничения частоты запросов (rate limiting) один-единственный клиент — злонамеренный или просто неправильно настроенный — может засыпать ваш API запросами: чтобы подобрать перебором, например, пароль через эндпоинт входа или просто чтобы перегрузить инфраструктуру. На практике это означает разумные лимиты запросов на пользователя или на API-ключ, понятный ответ клиенту, который упёрся в лимит, и более строгие ограничения для чувствительных эндпоинтов — входа и сброса пароля, — чем для обычных запросов на чтение.
Валидация входных данных: не доверяйте ничему, что приходит извне
Каждое поле каждого запроса нужно проверять на соответствие ожиданиям — тип, длину, формат, допустимый диапазон — прежде чем использовать его где-либо в логике приложения. Тот же принцип защищает от SQL-инъекций, но применим он гораздо шире: некорректные или неожиданные входные данные стоят за значительной долей реальных уязвимостей приложений, и далеко не только в запросах к базе данных.
Защита передачи данных: шифруйте всё, без исключений
Все запросы и ответы должны передаваться по HTTPS, без какой-либо возможности откатиться на незашифрованное соединение, даже для эндпоинтов, которые кажутся малорискованными. Современные инструменты (например, Let's Encrypt) позволяют настроить это практически бесплатно, так что оправданий пропустить этот пункт где-либо в API почти не бывает.
Продуманные сообщения об ошибках
Подробные сообщения об ошибках действительно полезны при разработке и действительно опасны в продакшене. Ошибка, раскрывающая внутренние пути к файлам, версию базы данных или полный стек вызовов, даёт злоумышленнику фору в поиске настоящей уязвимости. Ответы с ошибками в продакшене должны быть информативными ровно настолько, чтобы ими можно было пользоваться, — и не более.
Логирование и мониторинг
Нужна полноценная запись о том, кто, к чему и когда обращался, — не для того, чтобы что-то замедлить, а чтобы в случае проблемы было что расследовать, а не разводить руками. Отслеживание необычных закономерностей — скажем, когда один аккаунт внезапно начинает отправлять аномально много запросов, — позволяет заметить атаку на раннем этапе, до того как она перерастёт в настоящий инцидент.
Чек-лист, по которому стоит проверить свой API
- Требует ли каждый эндпоинт аутентификации, кроме тех, что намеренно сделаны публичными?
- Проверяет ли каждый запрос, что пользователь имеет право на доступ именно к этому ресурсу, а не просто вошёл в систему?
- Настроено ли ограничение частоты запросов, особенно для входа, сброса пароля и других чувствительных эндпоинтов?
- Проверяются ли все входные данные перед использованием, а не только те, что выглядели явно рискованными?
- Используется ли HTTPS везде, без исключений?
- Не раскрывают ли ответы с ошибками в продакшене внутренние детали реализации?
- Достаточно ли логов, чтобы потом действительно расследовать инцидент?
Тщательная проработка этого списка — эндпоинт за эндпоинтом, а не в общих чертах — это именно тот практический аудит безопасности приложений, который Burncode проводит для клиентов, наряду с усилением защиты инфраструктуры и подготовкой к реальному аудиту на соответствие требованиям.