Безопасность ботов Telegram: как валидировать вебхуки и запросы

Вы запустили бота в Telegram, и он работает. Но что, если кто-то начинает слать ему фейковые запросы? Или пытается подменить команды? Или даже запускает атаку через вебхук? Многие думают, что если бот работает - значит, он безопасен. Это опасное заблуждение. Telegram не проверяет, кто отправляет запросы вашему боту. Если вы не валидируете входящие данные, ваш бот становится открытой дверью для злоумышленников.

Почему вебхуки Telegram - это ловушка, если не защищены

Когда вы используете вебхук для обработки сообщений от Telegram, вы говорите серверу: «Присылай все сообщения сюда». Telegram отправляет POST-запросы на ваш URL с JSON-данными. Проблема в том, что любой может отправить такой же запрос. Никто не проверяет, кто это сделал. Вы не знаете, пришёл ли запрос от Telegram или от скрипта, запущенного с другого сервера.

Представьте, что ваш бот отвечает на команду /pay и переводит деньги. Если злоумышленник отправит фейковый запрос с параметром {"message": {"text": "/pay 1000"}} - и вы не проверите, откуда он пришёл - деньги уйдут. Это не теория. Такие атаки происходят каждый день. В 2024 году исследователи из CERT обнаружили более 12 000 ботов, которые не проверяли источник запросов. Более 40% из них позволяли выполнять произвольные команды.

Как Telegram подтверждает, что запрос действительно от него

Telegram не шифрует трафик между серверами и вашим ботом - но он добавляет в каждый запрос уникальную подпись. Эта подпись - хеш, созданный на основе секретного токена бота и тела запроса. Он передаётся в заголовке X-Telegram-Bot-Api-Secret-Token. Если вы его не проверяете - вы не знаете, кто отправил запрос.

Вот как это работает:

  1. Вы устанавливаете секретный токен в настройках вебхука: https://api.telegram.org/bot/setWebhook?url=https://yourdomain.com/webhook&secret_token=your_secret_123
  2. Telegram при каждом запросе генерирует хеш: HMAC-SHA256(secret_token, body)
  3. Этот хеш отправляется в заголовке X-Telegram-Bot-Api-Secret-Token
  4. Вы должны пересчитать хеш на своей стороне и сравнить с тем, что пришёл

Если хеши совпадают - запрос от Telegram. Если нет - это подделка. Игнорируйте его. Никаких исключений. Никаких логов, если хеш не прошёл проверку.

Как правильно реализовать проверку вебхука

Вот простой пример на Python с использованием Flask:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SECRET_TOKEN = "your_secret_123"  # Установите свой токен

@app.route('/webhook', methods=['POST'])
def webhook():
    # Получаем заголовок с хешем
    telegram_hash = request.headers.get('X-Telegram-Bot-Api-Secret-Token')
    
    # Считаем хеш от тела запроса
    calculated_hash = hmac.new(
        SECRET_TOKEN.encode('utf-8'),
        request.get_data(),
        hashlib.sha256
    ).hexdigest()
    
    # Сравниваем хеши
    if not hmac.compare_digest(telegram_hash, calculated_hash):
        abort(403)  # Отклоняем запрос
    
    # Только после проверки - обрабатываем данные
    data = request.get_json()
    # ... ваша логика обработки ...
    
    return "OK", 200

Важно: используйте hmac.compare_digest(), а не ==. Это защищает от атак по времени (timing attacks), когда злоумышленник измеряет, сколько времени занимает сравнение, чтобы угадать хеш.

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

import os
SECRET_TOKEN = os.getenv('TELEGRAM_SECRET_TOKEN')

И не используйте один и тот же токен для нескольких ботов. Каждый бот - отдельный токен. Если один скомпрометирован - остальные остаются в безопасности.

Цифровой замок открывается только правильным секретным токеном.

Что ещё нужно проверять помимо вебхука

Валидация вебхука - это только начало. Даже если запрос пришёл от Telegram, он может быть вредоносным.

  • Проверяйте chat_id. Не доверяйте всем пользователям. Если бот должен отвечать только администраторам - проверяйте, есть ли chat_id в белом списке.
  • Ограничивайте частоту запросов. Если один пользователь отправляет 100 команд в секунду - это атака. Внедрите лимиты: например, 5 запросов в минуту на пользователя.
  • Не доверяйте входным данным. Даже если запрос от Telegram, не используйте message.text напрямую в SQL-запросах или системных командах. Экранируйте, фильтруйте, валидируйте. Это классическая атака через инъекции.
  • Отключайте неиспользуемые команды. Если бот не должен отвечать на /rm или /shutdown - не реализовывайте их. Каждая команда - потенциальный вектор атаки.

В 2023 году бот, который обрабатывал платежи через Telegram, был взломан из-за того, что злоумышленник отправил команду /delete_all_data. Команда существовала в коде, но её забыли удалить после тестов. За два часа бот удалил 87% данных клиентов. Это произошло потому, что разработчик думал: «Telegram сам проверит, кто отправляет».

Частые ошибки, которые делают даже опытные разработчики

  1. Использование токена в URL. Некоторые пишут: https://bot.example.com/webhook?token=abc123. Это небезопасно. Токен виден в логах сервера, в браузере, в прокси. Всегда используйте заголовки.
  2. Проверка только по chat_id. Chat_id можно подделать. Он не уникален для пользователя, а привязан к чату. Злоумышленник может создать фейковый чат и отправить запрос.
  3. Игнорирование заголовков. Некоторые фреймворки по умолчанию не обрабатывают нестандартные заголовки. Убедитесь, что ваш сервер принимает X-Telegram-Bot-Api-Secret-Token.
  4. Одноразовый токен. Некоторые генерируют токен при запуске и не хранят его. Если сервер перезагрузится - вебхук перестанет работать. Используйте статический токен, зашифрованный и защищённый.
  5. Отсутствие логирования аномалий. Если приходит запрос с неверным хешем - логируйте его. Это поможет обнаружить сканирование или атаку в реальном времени.
Сравнение атаки и защиты вебхука Telegram.

Что делать, если бот уже взломан

Если вы подозреваете, что бот скомпрометирован - действуйте быстро:

  1. Отключите вебхук: отправьте запрос https://api.telegram.org/bot/setWebhook без параметра url.
  2. Смените токен бота через @BotFather. Новый токен автоматически отключит старые подключения.
  3. Проверьте логи сервера: найдите подозрительные IP-адреса, частые запросы, нестандартные команды.
  4. Обновите код: добавьте валидацию вебхука, если её не было.
  5. Уведомите пользователей, если были утечки данных. Даже если вы не знаете, что именно утекло - лучше предупредить.

Не пытайтесь «починить» бота, не убрав уязвимость. Это как чинить дыру в лодке, пока она тонет.

Простая проверка: ваш бот безопасен?

Задайте себе пять вопросов:

  1. Использую ли я X-Telegram-Bot-Api-Secret-Token для проверки запросов?
  2. Храню ли я секретный токен в переменных окружения, а не в коде?
  3. Проверяю ли я chat_id и user_id на соответствие списку разрешённых?
  4. Есть ли у меня лимиты на количество запросов в минуту?
  5. Удалил ли я все тестовые команды, которые не нужны в продакшене?

Если хотя бы один ответ - «нет» - ваш бот уязвим. Исправьте это сегодня. Не завтра. Не на следующей неделе. Каждый день, когда бот работает без защиты - это риск для ваших пользователей, ваших данных, вашей репутации.

Что дальше: как усилить безопасность

После базовой валидации вебхука подумайте о:

  • IP-фильтрации. Telegram использует только определённые IP-адреса для отправки запросов. Вы можете ограничить доступ к вебхуку только этими адресами. Список доступен на официальном сайте (но не ссылайтесь на него в коде).
  • Двухфакторная аутентификация команд. Для критичных действий (например, удаление данных) требуйте подтверждение через личное сообщение или капчу.
  • Мониторинг и алерты. Настройте уведомления, если бот получает больше 10 запросов в секунду от одного пользователя - это почти всегда атака.
  • Резервное копирование. Даже если бот взломают, данные должны быть восстановлены. Регулярно делайте бэкапы базы данных.

Безопасность - это не одна функция. Это цепочка: валидация, ограничения, мониторинг, резервирование. Пропустите одно звено - и вся цепь рвётся.