По данным Cloudflare Radar, в 2026 году доля человеческого трафика в интернете составила менее половины — 42,6%. Остальные 57,4% — боты. Это приблизительная оценка: однозначно отделить человеческий трафик от сгенерированного ботами довольно сложно. Запрос, сделанный человеком, может быть неотличим от запроса, сделанного ботом, даже с учетом всех возможных фингерпринтов, глобальных ID и отслеживания конкретных пользователей через счетчики.
Ботов пишут и в белых целях — например, для нагрузочного тестирования или проверки работоспособности фильтров. В серых целях используют разного рода накрутчики комментариев, лайков и репостов. Спамеры используют ботов для арбитража, чтобы собирать в соцсетях условно‑бесплатный трафик. Блекхеты с помощью ботов могут устраивать DDoS на сервисы, автоматизировать атаки или распространять малварь.
В любом случае — занимаешься ты пентестом, обычным QA или разработкой, тебе нужно знать, как пишутся и работают боты.
Автор против незаконного применения любых технологий, поэтому все, что выходит за рамки белого тестирования, останется за кадром. Тестовый бот, которого мы напишем, будет работать без прокси, пробива капчи и прочих приемов для обхода защиты и скрытия реального источника трафика.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Тестовый стенд
Для практики отлично подойдет OWASP Juice Shop. В лабе нет специальных фильтров или чего‑то подобного, зато можно регистрировать аккаунты и писать фидбэки. Этого вполне достаточно для безопасной демонстрации.
Для работы Juice Shop нужен Node.js. Если Node.js не установлен, скачиваем актуальную версию.
Выполняем такие команды:
git clone https://github.com/juice-shop/juice-shop.git --depth 1cd juice-shop
npm install
npm start
В файле hosts пропиши локальный домен juice.. Это нужно для корректной работы в Burp Suite. Строка для hosts:
127.0.0.1 juice.local
Открываем лабу в браузере: http://.
Бот на запросах
Самый быстрый и мощный вариант — повторить запросы, которые веб‑приложение отправляет серверу. Однако это работает не всегда: на сайте может быть огромное количество фильтров и механизмов защиты от прямого копирования запросов. Но небольшие ресурсы редко настолько заморачиваются: защита и фильтрация стоят серьезных денег.
Направляем трафик браузера через Burp и переходим в приложение Juice Shop. Регистрируем нового пользователя, затем оставляем отзывы о нескольких товарах. Это нужно, чтобы в Burp был полный набор запросов. Да, в Juice Shop есть уязвимость, позволяющая оставить отзыв без регистрации от имени любого пользователя системы. Но в этом случае я хочу показать полный процесс работы.

Полный список запросов:
POST /— создаем пользователя;api/ Users/ POST /— задаем ответ на секретный вопрос;api/ SecurityAnswers/ POST /— логинимся на сайте;rest/ user/ login PUT /— оставляем отзыв.rest/ products/ 1/ reviews
Создаем файл main., добавляем импорты и константы:
import requestsimport randomimport string# URL таргетаBASE = "http://juice.local:3000"# Файл с заготовленными отзывамиREVIEWS_FILE = "reviews.txt"Лучше, чтобы мыло и пароль генерировались случайно:
email = f"user{random.randint(10000,99999)}@test.com"password = "".join(random.choices(string.ascii_letters + string.digits, k=12))answer = "Bums"Фишка Gmail
Если ты пишешь свой ресурс, для защиты от ботоферм тебе стоит знать нюансы работы почтовиков. Например, любимый многими Gmail не учитывает точки в логинах. Для почтовика адреса ivanivanovich, ivan. и ivan.. равнозначны. Точек может быть огромное количество. Если на твоем сайте доступна регистрация через Gmail, при проверке на дубликаты почты отбрасываем точки. Иначе спамеры, не стесняясь, забьют твою базу одним и тем же адресом.
Чтобы отзывы были более‑менее разнообразными, положим их в отдельный файл и будем вытаскивать из него случайную строку:
with open(REVIEWS_FILE, encoding="utf-8") as f: lines = [line.strip() for line in f if line.strip()]message = random.choice(lines)
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
