Как защитить эндпоинт от выгрузки всей базы данных по одному запросу
Что проверяют
Понимаете ли вы, что защита живёт только на сервере. Ограничение в интерфейсе ничего не решает: запрос из DevTools или curl с limit=1000000 идёт мимо любого фронтенда. Для фронтенд-разработчика это актуально, если вы пишете BFF, роуты Next.js или GraphQL-слой. Следом спрашивают, как отличить легальную выгрузку от скрейпинга.
Как отвечать
В OWASP API Security Top 10 редакции 2023 года это пункты про неограниченное потребление ресурсов и авторизацию на уровне объектов. Каркас ответа:
- потолок размера страницы: сервер обрезает
limitдо максимума, например 100, что бы ни прислал клиент. Пагинация по курсору вместоoffsetзаодно не даёт дёшево прыгать в конец таблицы; - авторизация на уровне объекта: фильтр по владельцу или тенанту стоит в самом запросе к базе, пользователь получает только свои записи;
- только нужные поля: сервер отдаёт DTO под экран, а не всю строку таблицы;
- ограничение частоты: rate limit по токену и по IP на шлюзе, в nginx (
limit_req) или в middleware, ответ429с заголовкомRetry-After; - GraphQL: лимиты глубины и сложности запроса, ограничение вложенных списков, в продакшене только заранее зарегистрированные (persisted) запросы;
- непредсказуемые идентификаторы: UUID вместо последовательных
id, чтобы записи нельзя было перебрать циклом; - мониторинг: алерт на аномальный объём по одному токену, аудит массовых выгрузок.
Если бизнесу нужна полная выгрузка, её выносят в отдельную асинхронную задачу с правами, аудитом и ссылкой на файл, а не открывают обычный список.
Где спотыкаются
Отвечают «добавим пагинацию на фронте». Пагинация без серверного потолка остаётся подсказкой, а не ограничением.
Считают, что аутентификации достаточно. Любой залогиненный пользователь, пройдя циклом по страницам, выгрузит всё, если нет проверки прав на объекты и лимита частоты.
Прячут лишние поля в интерфейсе, но отдают их в JSON. Для атакующего вкладка «Сеть» в DevTools и есть интерфейс.