Защита веб-форм от ботов: чек-лист перед продакшеном
Форма может принимать спам, запускать дорогие операции и создавать дубли даже при установленной CAPTCHA. Чек-лист помогает проверить лимиты, CSRF, повторную отправку, серверную валидацию и мониторинг до релиза.

Форма регистрации, обратной связи или оплаты может принять тысячи автоматических запросов за считаные минуты, даже если на странице уже стоит CAPTCHA. Перед продакшеном нужно проверить не один виджет, а весь путь запроса: токен, лимиты, серверную валидацию, защиту от повторов, журналы и реакцию на всплеск. Ниже — практический чек-лист для веб-приложений, актуальный как набор принципов для современных браузеров и серверных фреймворков; конкретные названия настроек зависят от вашего стека.
Сначала определите, что именно вы защищаете
Автоматическая отправка — не всегда атака одного типа. Бот может массово создавать аккаунты, забивать форму спамом, проверять утёкшие учётные данные или повторять дорогую операцию. Для каждой формы зафиксируйте действие, его стоимость и допустимую частоту.
- Обратная связь: риск спама, рассылки и переполнения очереди поддержки.
- Регистрация: риск массовых аккаунтов, злоупотребления письмами и обхода бизнес-ограничений.
- Восстановление пароля: риск перебора, перечисления пользователей и массовой отправки писем.
- Платёж или заказ: риск повторной операции, финансового ущерба и нагрузки на внешние сервисы.
- Поиск и фильтры: риск дорогих запросов к базе данных и истощения ресурсов.
Не ставьте одинаковый лимит на все маршруты. Запрос поиска и создание заказа имеют разную цену, поэтому и защита должна быть разной.
CAPTCHA усложняет работу боту, но не отвечает на главный вопрос: может ли сервер безопасно отклонить лишний, повторный или поддельный запрос.
Чек-лист перед выпуском
1. Сервер не доверяет данным из браузера
Проверьте, что сервер сам проверяет обязательные поля, длину строк, формат адреса электронной почты, диапазоны чисел и допустимые значения перечислений. Проверка JavaScript в браузере нужна для удобства, но не является границей безопасности: запрос можно отправить напрямую, минуя интерфейс.
Для каждого поля должны быть известны максимальная длина и правило нормализации. Лишние поля сервер должен игнорировать или отклонять, а не принимать автоматически. Особенно опасно без проверки принимать идентификатор пользователя, цену, роль, скидку или адрес доставки.
Проверка: отправьте запрос с изменёнными полями через клиент для тестирования HTTP или автоматизированный тест. Сервер не должен принимать значения, которые пользователь не имел права менять.
2. CSRF-защита включена там, где запрос меняет состояние
Для форм, которые создают аккаунт, меняют профиль, оформляют заказ или запускают другую операцию, проверьте механизм защиты от CSRF. Токен должен проверяться на сервере, быть связан с пользовательской сессией или другим доверенным контекстом и не приниматься из произвольного места.
Одной настройки cookie SameSite недостаточно как универсальной защиты: поведение зависит от сценария, доменов, переходов и используемых методов аутентификации. Если приложение работает на нескольких доменах или принимает запросы из отдельного фронтенда, отдельно проверьте разрешённые источники и правила CORS.
Проверка: запрос без CSRF-токена, с просроченным токеном и с токеном от другой сессии должен быть отклонён. Ошибка не должна раскрывать внутренние детали приложения.
3. Лимиты стоят на правильном уровне
Ограничивайте не только IP-адрес. За NAT, мобильной сетью или корпоративным прокси могут находиться сотни обычных пользователей, а распределённый ботнет, наоборот, меняет адреса. Для чувствительных форм полезно учитывать сочетание признаков: учётную запись, сессию, IP, маршрут и стоимость операции.
Лимит должен быть связан с ответом сервера: при превышении возвращайте понятный отказ и не запускайте побочные действия. Если используется HTTP-ответ 429 Too Many Requests, согласуйте его с клиентом и при необходимости указывайте время ожидания. Точные значения нельзя брать «из интернета»: снимите базовую частоту легитимных отправок и задайте отдельные пороги для обычного трафика и аварийного режима.
Проверка: серия запросов превышает лимит, но не приводит к отправке новых писем, созданию заказов или повторным вызовам платёжного провайдера.
4. CAPTCHA включается по риску, а не заменяет всю защиту
CAPTCHA может быть полезна после подозрительной серии запросов, при массовой регистрации или перед дорогой операцией. Не делайте её единственным барьером: автоматизация может обходить виджет, а сторонний сервис может работать с ним через браузер.
Проверяйте результат CAPTCHA на сервере, учитывайте срок действия токена и не принимайте его как доказательство личности пользователя. Проверьте доступность: форма не должна становиться непроходимой для людей, использующих экранные дикторы, клавиатурную навигацию или ограниченный браузер.
Проверка: сервер отклоняет отсутствие, просрочку и повторное использование ответа CAPTCHA. При недоступности внешнего сервиса есть безопасный сценарий отказа, а не бесконечные повторы.
5. Повторная отправка не создаёт вторую операцию
Двойной клик, обновление страницы и повтор после сетевого тайм-аута — обычные ситуации, а не обязательно действия бота. Для заказа, платежа, выдачи бонуса и другой неповторяемой операции используйте идемпотентный идентификатор, который сервер связывает с результатом операции и контекстом пользователя.
Ключ должен иметь ограниченный срок жизни и не должен позволять одному клиенту повторно выполнить операцию с изменёнными критическими параметрами. В базе данных нужны ограничения, которые не дадут создать дубликат при гонке двух запросов.
Проверка: два одинаковых запроса с одним идентификатором дают один бизнес-результат. Повтор с тем же идентификатором, но другой суммой или товаром, отклоняется.
6. Ошибки не раскрывают лишнего
Ответ «пользователь с таким адресом уже зарегистрирован» помогает перечислять существующие аккаунты. Для регистрации и восстановления доступа используйте сообщения, которые не раскрывают наличие учётной записи, если это соответствует модели угроз. При этом сообщение должно объяснять следующий безопасный шаг.
Не возвращайте в форму трассировку, SQL-ошибки, внутренние идентификаторы, содержимое исключений и результат проверки антибот-сервиса. Подробности отправляйте в защищённые журналы с контролем доступа.
7. Логи и метрики позволяют доказать, что защита работает
Минимальный набор наблюдения: число отправок по маршруту, доля ответов 4xx и 429, ошибки CSRF, срабатывания CAPTCHA, повторные операции, задержка ответа и объём запросов по регионам или сетям. Логируйте идентификатор запроса, время, маршрут и результат, но не пароли, токены, полные платёжные данные и содержимое формы без необходимости.
Настройте оповещение не только на рост трафика. Иногда атака выглядит как обычная частота запросов, но резко увеличивает стоимость отправки писем, обращений к базе или вызовов внешнего API.
Какой контроль для какой угрозы
| Механизм | Что закрывает | Цена и ограничение | Что проверить |
|---|---|---|---|
| Серверная валидация | Поддельные и некорректные данные | Нужны правила для каждого поля | Запрос без браузерной проверки |
| CSRF-токен | Запросы от чужого сайта в контексте вашей сессии | Сложнее интеграция фронтенда и API | Отсутствующий, чужой и просроченный токен |
| Rate limit | Массовые и слишком частые отправки | Риск задеть пользователей за общим IP | Лимит по нескольким признакам |
| CAPTCHA | Часть автоматизированных сценариев | Хуже доступность и зависимость от внешнего сервиса | Проверка токена на сервере и запасной отказ |
| Идемпотентность | Дубли из-за повторов и сетевых сбоев | Нужны хранилище ключей и правила срока жизни | Повтор запроса и гонка двух запросов |
Термин: идемпотентность — свойство операции, при котором повторение одного и того же запроса не меняет результат после первого успешного выполнения. Для платежа это означает не «запретить второй HTTP-запрос», а не списать деньги дважды.
Что ломается в продакшене
Лимит срабатывает на прокси, а не на пользователя
Если приложение видит только адрес балансировщика, весь трафик может попасть в одно ограничение. Не доверяйте заголовкам с адресом клиента без корректной настройки доверенной цепочки прокси: их можно подделать. Опишите, какой компонент добавляет адрес, где он проверяется и какой слой применяет лимит.
CAPTCHA проверяется только в интерфейсе
Спрятанная кнопка, отключённая кнопка или проверка JavaScript не защищают endpoint. Отправьте запрос напрямую: сервер должен сам проверить токен, лимиты и права, а не рассчитывать на поведение страницы.
Защищена форма, но не её побочные действия
Форма может отклонять лишние запросы, но очередь, отправка письма или вызов внешнего сервиса запускаются до проверки лимита. Проверки, которые экономят ресурсы, размещайте до дорогих операций. Для повторяемых задач добавьте дедупликацию в очереди и контроль результата на стороне потребителя.
Ручное тестирование не воспроизводит реальную нагрузку
Составьте небольшой сценарий: нормальная отправка, пустые и слишком длинные поля, отсутствие токена, серия запросов, повтор операции, параллельные запросы и тайм-аут внешнего сервиса. Выполняйте его на тестовом окружении с теми же прокси и настройками лимитов, что будут в продакшене. Не направляйте нагрузочный тест на чужие сервисы и рабочую платёжную инфраструктуру.
Что сделать после чек-листа
Сохраните результаты проверок как тесты, привяжите каждый лимит к метрике и назначьте владельца тревог. После релиза первые дни смотрите не только на количество отказов, но и на стоимость писем, долю дублей, ошибки внешних антибот-сервисов и обращения пользователей, которым форма стала недоступна.
Следующий полезный шаг — пересмотреть форму вместе с владельцем бизнес-операции: какие поля действительно нужны, какие действия можно отложить до подтверждения адреса и какие операции обязаны быть идемпотентными. Инвалидация сессий и защита уже существующей учётной записи — отдельная тема; здесь важна именно безопасность отправки формы и её побочных действий.
Тендерный специалист 44-ФЗ / 223-ФЗ: Разбор PDF-документации закупки, поиск «заточек» под поставщика, чек-лист заявки.
Спросить за 20 ₽Источники: OWASP Automated Threats to Web Applications, OWASP Cross-Site Request Forgery Prevention Cheat Sheet
Частые вопросы
Достаточно ли поставить CAPTCHA на форму?
Какой лимит запросов выбрать для формы?
Нужен ли CSRF-токен для JSON API?
Что делать, если пользователь нажал кнопку отправки дважды?
Что будет, если я не успел настроить защиту до релиза?
Почему лимит не работает после установки CDN или reverse proxy?
Что проверить в продакшене после релиза?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.