Перейти к основному содержимому

Как защитить форму SMS-авторизации от накрутки

Для кого это руководство

Для компаний, которые отправляют через REDSMS SMS-коды при регистрации, входе и подтверждении операций. Здесь — как распознать накрутку SMS (SMS pumping), ограничить её последствия и настроить несколько уровней защиты.

Главное

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

Что такое накрутка SMS​

SMS pumping (накрутка SMS) — искусственное увеличение числа сообщений, обычно через публичную форму регистрации, входа или восстановления доступа. Бот запрашивает код, ваше приложение отправляет SMS, но пользователь не завершает подтверждение.

Результат для компании — рост расходов на SMS: все отправленные сообщения оплачиваются независимо от статуса доставки.

Типичный сценарий​

  1. Бот находит публичную точку запроса кода — форму на сайте или её серверный API.
  2. Запрашивает коды на множество номеров, нередко по одному сообщению на номер.
  3. Ваше приложение отправляет SMS через REDSMS.
  4. Код никто не вводит, а расходы на отправки растут.
  5. Бот меняет номера, IP-адреса и параметры запросов, обходя простые лимиты.

Как распознать атаку​

Обратите внимание на сочетание признаков:

  • количество отправленных кодов резко выросло без роста реальных регистраций или входов;
  • много новых номеров и мало повторных запросов на один номер;
  • номера идут подряд, из одного диапазона или из стран, где у вас нет пользователей, — если вы ещё не ограничили страны (см. шаг 3);
  • растёт число разных номеров с одного IP, устройства, сессии или группы связанных IP;
  • растут расходы на авторизацию, а доля успешно подтверждённых кодов падает.

Важнее всего сравнивать отправки с результатом. Например, если SMS стало втрое больше, а успешных подтверждений столько же, — проверьте трафик. Универсального «нормального» соотношения нет: ориентируйтесь на исторические показатели своего продукта.

Частые причины атаки​

Атаки производят с целью нанесения финансового ущерба, перегрузки системы или использования чужого API-ключа. Поэтому защита должна работать независимо от мотивов атакующего.

Чек-лист защиты​

  • Капча на форме авторизации, её токен проверяется на сервере
  • Ключ API REDSMS не попадает в браузер или мобильное приложение
  • Повторная отправка на номер — не чаще одного раза в 60 секунд
  • Ограничено число кодов на один номер за сутки
  • Ограничено число разных номеров, на которые можно запросить код с одного источника
  • Есть лимит общего количества кодов и контроль расходов за период; проверка выполняется на сервере
  • Разрешены только нужные страны и направления (для России — мобильные +79)
  • В личном кабинете REDSMS включены ограничения и белый список IP
  • Ведётся учёт отправленных и успешно подтверждённых кодов; проверка выполняется на сервере
  • Настроены оповещения об аномалиях и понятен порядок действий при атаке

Значения лимитов в этом руководстве — примеры. Подберите их под свой трафик.

Шаг 1. Подключите капчу​

Капча снижает число автоматических обращений, но не заменяет лимиты и анализ поведения. Главное правило: токен капчи проверяется на вашем сервере до отправки SMS. Если проверять только в браузере, бот обойдёт её, обратившись к серверу напрямую.

Для аудитории в России удобна Yandex SmartCaptcha, популярный зарубежный вариант — Cloudflare Turnstile.

Yandex SmartCaptcha​

  1. Создайте капчу в консоли Yandex Cloud и получите два ключа: ключ клиента (для страницы) и серверный ключ (только для сервера, никому не передавайте).

  2. Добавьте виджет в форму:

    <script src="https://smartcaptcha.cloud.yandex.ru/captcha.js" defer></script>

    <form method="post" action="/auth/send-code">
    <input name="phone" type="tel" autocomplete="tel" placeholder="+7 900 000-00-00" required>
    <div class="smart-captcha" data-sitekey="<КЛЮЧ_КЛИЕНТА>"></div>
    <button type="submit">Получить код</button>
    </form>

    После прохождения капчи в форму автоматически добавляется скрытое поле smart-token.

  3. На сервере, до отправки SMS, проверьте токен: POST https://smartcaptcha.cloud.yandex.ru/validate с параметрами secret (серверный ключ), token и, по возможности, ip (IP пользователя). Капча пройдена, если в ответе "status": "ok". Отсутствующий или недействительный токен — это не пройденная проверка.

Заранее решите, что делает сайт, если сервис капчи недоступен: для чувствительных операций безопаснее не отправлять SMS без дополнительной проверки.

Cloudflare Turnstile​

Работает так же: виджет <div class="cf-turnstile" data-sitekey="..."> со скриптом https://challenges.cloudflare.com/turnstile/v0/api.js, токен приходит в поле cf-turnstile-response. На сервере проверьте его запросом к https://challenges.cloudflare.com/turnstile/v0/siteverify с параметрами secret, response и remoteip; капча пройдена, если "success": true. Не доверяйте одному факту отображения виджета в браузере.

Дополнительно

Запретите встраивание ваших страниц в чужие сайты заголовком Content-Security-Policy: frame-ancestors 'self'. Это полезно против отдельных сценариев злоупотребления интерфейсом, но не защищает от накрутки SMS само по себе.

Шаг 2. Ограничьте частоту и число получателей​

Все ограничения проверяйте на своём сервере до обращения к API REDSMS.

Что ограничитьПример начального порогаДля чего
Повторная отправка на один номерНе чаще 1 раза в 60 секундПредотвратить частые повторы
Коды на один номерНе более 5 за 24 часаОграничить расходы на одного получателя
Запросы с одного IPНе более 10 за 10 минутСнизить частоту прямых запросов
Разные номера с одного IP или сессииНе более 3 за часПомешать перебору получателей — главный признак накрутки
Общий объём кодовПорог по обычному трафикуСдержать распределённую атаку
Расход на авторизациюБюджет и пороги предупреждения на вашей сторонеОграничить финансовые потери
Лимит разных номеров — самый важный

При накрутке боты отправляют по одному SMS на множество разных номеров. Ограничение повторов на один номер такую атаку не остановит. Атакующий может распределять запросы между множеством IP, поэтому учитывайте и совокупный объём, уникальные номера, диапазоны получателей, сессии и долю подтверждённых кодов.

Подбирайте значения под свою аудиторию: несколько добросовестных пользователей могут выходить в интернет с одного IP — корпоративная сеть, мобильный оператор. В таких случаях вместо безусловной блокировки по IP запрашивайте дополнительную проверку.

Для счётчиков используйте атомарные операции и временные окна в Redis или похожем хранилище. Проверка лимита и резервирование квоты должны выполняться согласованно при параллельных запросах. Не продлевайте окно при каждом запросе, если нужен фиксированный лимит за период.

Шаг 3. Отправляйте коды только с сервера​

Правильная цепочка: браузер пользователя → сервер вашего сайта → проверка номера, капчи и лимитов → API REDSMS → результат отправки → проверка введённого кода.

  • Ключ API REDSMS хранится только на сервере — никогда в HTML, JavaScript или мобильном приложении.
  • Защитите серверный метод отправки кода так же, как форму: капча и лимиты проверяются в нём самом.
  • Проверяйте формат и страну номера. Если ваши пользователи только в России, принимайте мобильные номера +79 и отклоняйте остальные. Это грубый первичный фильтр, а не полноценная валидация номера. Учтите: код +7 общий у России и Казахстана — мобильные номера Казахстана начинаются с +77.

Что должен делать сервер​

  1. Получить номер, токен капчи и контекст запроса.
  2. Привести номер к международному формату.
  3. Проверить, разрешены ли страна и направление.
  4. Проверить капчу на сервере.
  5. Атомарно проверить и зарезервировать лимиты: номер, IP, сессия, уникальные номера, общий объём.
  6. Если для пользователя ещё действует выданный код, не создавать новое сообщение без необходимости.
  7. Сгенерировать криптографически случайный одноразовый код.
  8. Сохранить его безопасный проверочный эквивалент (например, хеш) с коротким сроком действия и привязкой к операции.
  9. Вызвать API REDSMS и проверить HTTP-ответ и результат API.
  10. Записать событие и результат отправки в журнал.
  11. При вводе кода проверить срок действия и число попыток, а после успеха сразу сделать код недействительным.

Для типовой SMS-авторизации подойдут шестизначный код, короткий срок действия (например, 3–5 минут) и жёсткое ограничение числа попыток ввода.

Пример серверной логики (Python)​

Это схема, а не готовый код для копирования: адаптируйте её под свой язык и фреймворк, а поля и способ подписи запроса сверяйте с актуальной документацией API REDSMS.

import hashlib, secrets, time
import redis, requests

r = redis.Redis()

ALLOWED_PREFIXES = ("+79",) # мобильные РФ; добавьте "+77", если есть пользователи из Казахстана

def captcha_ok(token, ip):
resp = requests.post("https://smartcaptcha.cloud.yandex.ru/validate",
data={"secret": SMARTCAPTCHA_SERVER_KEY, "token": token, "ip": ip},
timeout=3)
return resp.ok and resp.json().get("status") == "ok"

def within_limit(key, limit, window_sec):
pipe = r.pipeline()
pipe.incr(key)
pipe.expire(key, window_sec, nx=True) # окно задаётся один раз и не продлевается
count, _ = pipe.execute()
return count <= limit

def unique_phones_ok(ip, phone, limit=3, window_sec=3600):
key = f"phones:{ip}"
pipe = r.pipeline()
pipe.sadd(key, phone)
pipe.expire(key, window_sec, nx=True)
pipe.scard(key)
_, _, count = pipe.execute()
return count <= limit

def send_code(phone, ip, captcha_token):
if not captcha_ok(captcha_token, ip):
return "Пройдите проверку"
if not (phone.startswith(ALLOWED_PREFIXES) and len(phone) == 12):
return "Неверный номер"
if not within_limit(f"phone:60s:{phone}", 1, 60):
return "Повторная отправка через 60 секунд"
if not (within_limit(f"phone:day:{phone}", 5, 86400)
and within_limit(f"ip:10m:{ip}", 10, 600)
and unique_phones_ok(ip, phone)):
return "Слишком много запросов, попробуйте позже"

code = f"{secrets.randbelow(1_000_000):06d}"
save_code(phone, code) # ваша функция: сохранить хеш кода на 3–5 минут, с лимитом попыток

ts = str(time.time())
signature = hashlib.md5((ts + REDSMS_API_KEY).encode()).hexdigest()
resp = requests.post("https://cp.redsms.ru/api/message",
headers={"login": REDSMS_LOGIN, "ts": ts, "secret": signature},
json={"route": "sms", "from": SENDER_NAME, "to": phone,
"text": f"Код для входа: {code}"},
timeout=10)
if not (resp.ok and resp.json().get("success")):
log_send_error(phone, resp) # ваша функция: журнал ошибок отправки
return "Не удалось отправить код, попробуйте позже"
return "Код отправлен"

Принятие сообщения API ещё не означает доставку абоненту: статус доставки приходит позже (метод GET /api/message/{uuid} или Webhook).

Как не допустить лишних повторов​

  • Показывайте таймер: «Отправить код повторно через 60 с».
  • Не отправляйте новое SMS автоматически при перезагрузке страницы.
  • Если код ещё действует, предложите дождаться его, а не сразу создавайте новый.

Шаг 4. Включите ограничения в личном кабинете REDSMS​

Это вторая линия защиты: она сработает, даже если что-то пропустит ваш сайт.

НастройкаГдеЧто даёт
Суточный лимит отправленных сообщенийНастройки → ОграниченияВерхняя граница количества отправок за сутки
Максимум одинаковых сообщений на номер за суткиНастройки → ОграниченияОграничивает повторы одинакового текста на один номер
Интервал, в течение которого сообщения на номер считаются дубликатамиНастройки → ОграниченияОтсекает частые одинаковые отправки
Белый список IP для APIНастройки → HTTP APIЗапросы не с ваших серверов получат ответ 401

Суточные лимиты сбрасываются в 03:00 по Москве. Подбирайте общий лимит с учётом ожидаемого числа регистраций и пикового трафика.

Чего эти настройки не делают
  • Белый список IP защищает ваш ключ от использования с чужих серверов, но не остановит бота, который обращается к публичной форме вашего сайта: в этом случае SMS отправляет ваш собственный сервер — с разрешённого IP.
  • Лимит дубликатов не заменяет защиту от массовой отправки на разные номера. К тому же из-за разных одноразовых кодов тексты SMS отличаются друг от друга.
  • Суточный лимит ограничивает количество сообщений, а не сумму расходов. Денежный порог настраивайте на своей стороне.

Шаг 5. Отслеживайте аномалии и расходы​

Собирайте события не только об отправке SMS, но и об успешном подтверждении кода — вторые есть только на стороне вашего сайта. Детализацию отправок смотрите в личном кабинете REDSMS: число сообщений, номера, страны.

ПоказательЧто показывает
Отправленные коды в час и за суткиНеобычные скачки объёма
Уникальные номера-получателиМассовый перебор абонентов
Доля успешных подтвержденийПриводят ли отправки к реальной авторизации
SMS на одно успешное подтверждениеИзменение эффективности канала
Расходы по направлениямРост стоимости отдельных стран и сетей
Запросы по IP и сессиямКонцентрацию или распределение подозрительной активности
Причины отказов и срабатывания лимитовПоведение ботов и влияние защиты на обычных пользователей

Не задавайте универсальное правило вроде «1,2 SMS на один успешный вход». Рассчитайте собственный базовый уровень — например, за предыдущие 2–4 недели — и ищите отклонения с учётом времени суток, сезонности и маркетинговых кампаний. Для регистрации, входа и восстановления пароля могут понадобиться разные пороги.

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

Если накрутка уже идёт​

  1. Ограничьте ущерб: временно снизьте суточный лимит в личном кабинете REDSMS (Настройки → Ограничения) и отключите в своём приложении неиспользуемые международные направления.
  2. Усильте серверные проверки: капча, лимит разных номеров, ограничения по IP и сессии из шагов 1–2.
  3. Разберите трафик: когда начался рост, какие страны, диапазоны номеров и источники запросов задействованы.
  4. Проверьте ключ API: если есть признаки, что он попал к посторонним, сгенерируйте новый и включите белый список IP (Настройки → HTTP API).
  5. Напишите в поддержку REDSMS: укажите логин, период аномалии, направления и примеры сообщений — мы оценим детализацию и подскажем, какие можно установить ограничения в личном кабинете.
  6. После атаки пересмотрите пороги и настройте оповещения, чтобы следующий всплеск заметить раньше.

Не отключайте подтверждение кодом целиком, не оценив последствия для пользователей: для рискованных запросов лучше временно включить дополнительную проверку.

Другие способы подтверждения​

В зависимости от сценария можно рассмотреть другие каналы REDSMS:

КаналКак работает
TelegramКод приходит в Telegram; оплата только за доставленные коды
Wait CallПользователь сам звонит на номер для подтверждения
Flash CallКод — последние цифры номера входящего звонка
SIM-PUSH / Mobile IDПодтверждение одним нажатием во всплывающем окне на телефоне
VoiceКод озвучивается голосовым звонком

Доступность, тарифы, ограничения и условия доставки каждого канала можно уточнить у вашего менеджера.

Переход с SMS на звонок или другой платный канал сам по себе не устраняет риск накрутки: для любого способа подтверждения нужны лимиты, контроль получателей и мониторинг расходов.

Коротко: минимальная безопасная конфигурация​

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