Каждый отдельный метод (и даже все вместе) — не гарантирует защиту, но снижает вероятность и ущерб, увеличивает стоимость атаки.
Значения параметров в примерах можно менять.
Методы могут (и должны) комбинироваться и дополняться.
Примеры на PHP являются лишь иллюстрацией.
Цель — не сделать атаку невозможной, но дороже выгоды.
Некоторые тезисы и примеры имеют допущения и нюансы, развитие описания которых не уместить в рамках этой заметки.
Конкурентам: расход бюджета на уведомления конкурентами (по аналогии со скликиванием контекстной рекламы).
Конкурентам: жалобы на спам от абонентов, штрафы от операторов и регуляторов.
Конкурентам: нарушение нормальной работы формы регистрации или сайта для легитимных пользователей.
Спамерам: дешевый способ “бомбинга” определенных абонентов на заказ.
Спамерам: фейковые регистрации.
Атакующему выгодна возможность выполнить максимальное количество запросов за минимальное время с одного устройства. Повторный запрос кода подтверждения с одного IP адреса или на один номер следует разрешать не ранее, чем через 90-120 секунд. А лучше - увеличивать это время с каждым повторным запросом. Эту проверку следует осуществлять не только в интерфейсе браузера, но и на серверной стороне.
$ip = $_SERVER['REMOTE_ADDR'];
$phone = $_POST['phone'];
$isLimited = apcu_fetch($ip) || apcu_fetch($phone);
apcu_store($ip, 1, 90);
apcu_store($phone, 1, 90);
if ($isLimited) {
// deny
}
Как улучшить: использовать browser fingerprinting [1] [2] и exponential backoff [1] [2].
IPv4 адреса в мире закончились, а их аренда стоит денег, что увеличивает стоимость ресурсов атакующего. Адреса IPv6 же практически бесплатны и безграничны, потому поддержку IPv6 лучше отключить.
Стоимость аренды 1 IPv4 адреса ~100₽, а отправки SMS — ~4₽, что делает невыгодным атаку при <20 запросов с одного IP. Пример ограничения для 5 запросов с одного IP в сутки:
$ip = $_SERVER['REMOTE_ADDR'];
$hits = apcu_fetch($ip) ? apcu_inc($ip) : intval(apcu_store($ip, 1, 86400));
if ($hits > 5) {
// deny
}
Как улучшить: автоматически добавлять IP-адреса в запрещенные на уровне фаервола или веб-сервера [1] [2] [3] [4]. В примитивном варианте это может выглядеть так:
if ($hits > 5) {
@fwrite(fopen('/var/log/spam.log', 'a'), "deny $ip;\n");
}
// nginx.conf:
server {
include /var/log/spam.log;
allow all;
// crontab:
*/5 * * * * /etc/init.d/nginx reload
При отправке сообщения через api.greensms.ru повторный запрос идёт альтернативным маршрутом, чтобы гарантировать доставку. Последующее сообщения будут направлены теми же маршрутами, потому, если предположить, что они по каким-то причинам не были получены — дальнейшие повторы нецелесообразны.
Пример ограничения для 5 запросов на один номер в сутки:
$phone = $_POST['phone'];
$hits = apcu_fetch($phone) ? apcu_inc($phone) : intval(apcu_store($phone, 1, 86400));
if ($hits > 5) {
// deny
}
Как улучшить: начиная с 3-го запроса использовать код в номере, входящий звонок, код голосом, VK, WhatsApp, Viber вместо SMS; запретить отправку в страны, в которых нет ваших пользователей.
Наличие в форме уникального одноразового токена и его проверка на серверной стороне немного усложняет задачу атакующему, поскольку гарантируют, что запрос отправлен лишь после предварительной загрузки формы. Детали примере Laravel можно почерпнуть из документации.
Как улучшить: проверять, отправлен ли запрос посредством AJAX [1], использовать SameSite Cookie [1]
reCAPTCHA v3 является “скрытой” формой проверки, не требующей со стороны пользователя решения задач или ввода текста. В результате работы сервис возвращает значение в диапазоне от 0 до 1, означающее вероятность того, что пользователь — человек.
На практике, значения от 0,3 могут присваиваться легитимным пользователям, потому для полноценной фильтрации могут быть использованы лишь значения <0,3. В остальных случаях необходима комбинация с другими методами, возможность пользователю подтвердить, что он не робот другим способом.
Помимо этого, поскольку метод использует browser fingerprinting — наблюдаются ботнеты, способные стабильно показывать результат в 0,9. Всплеск активности на скриншоте — нелегитимный трафик с оценкой 0,9.
Как улучшить: дополнить отображением reCAPTCHA v2 в сомнительных случаях, например при оценке в диапазоне 0,3-0,7 или повторных действиях.
Если вы не ведете бизнес в каких-либо регионах, вы можете ограничить для них доступ или блокировать отправку на соответствующие номера.
Можно ограничить доступ для известных ботов и инструментов разработки на основе заголовков User-Agent и Referer.
Как улучшить: блокировать IP адреса дата-центров и хостинг-провайдеров.
Cloudflare, Qrator, DDoS-Guard предлагают не только решения по защите от DDoS, но и от ботов. Но и это не панацея.