Лучшие практики безопасности для ботов Telegram
Токен бота, это пароль, которым может воспользоваться кто угодно и откуда угодно, без второго фактора и без уведомления о входе. Большинство инцидентов с Telegram-ботами начинаются именно здесь. Вот что нужно закрыть, в том порядке, в котором обычно всё идёт не так.
1. Относитесь к токену как к действующей учётной записи
Тот, у кого есть токен вашего бота, полностью контролирует бота. Он может читать входящие сообщения, отправлять сообщения от вашего имени и изменить ваш вебхук так, что ваш собственный сервер перестанет получать обновления. Никакого запроса пароля и подтверждения устройства на этом пути нет.
Где утекают токены
- Попадают в коммит репозитория. Самый распространённый путь, и публичные репозитории постоянно сканируются ботами, которые вам не принадлежат.
- Вставляются в чат поддержки или в трекер задач. Как только токен попал в тикет, он оказывается где-нибудь в поисковом индексе.
- Зашиваются напрямую в мобильную или фронтенд-сборку. Всё, что доставляется на клиентское устройство, становится публичным.
- Остаются в логах. Если вы логируете полный URL API, токен оказывается прямо в URL.
Что делать вместо этого
- Храните токен в переменной окружения или в менеджере секретов, никогда в исходном коде.
- Добавьте
.envв.gitignoreдо первого коммита, а не после. - Скрывайте токен в выводе логов.
- Используйте разные токены для разработки и продакшена, чтобы утёкший тестовый токен не мог затронуть реальных пользователей.
Если токен утёк, отзовите его
Откройте BotFather, выполните /revoke и выберите бота. Старый токен сразу перестаёт работать, и вы получаете новый. Ротация стоит нескольких минут простоя. Оставить всё как есть стоит бота. Переписывание истории git не поможет, потому что токен уже собрали.
2. Защитите вебхук
Если ваш бот использует вебхук, этот URL, это открытая точка доступа в интернете. Любой, кто её найдёт, сможет публиковать поддельные обновления, неотличимые от настоящего трафика Telegram.
- Задайте секретный токен. Метод
setWebhookпринимает параметрsecret_token. Telegram затем возвращает его в заголовкеX-Telegram-Bot-Api-Secret-Tokenпри каждом запросе. Отклоняйте всё, что не совпадает. - Используйте HTTPS с действующим сертификатом. Telegram требует этого, и это не позволяет прочитать содержимое во время передачи.
- Используйте непредсказуемый путь. Случайный сегмент в URL сам по себе не является настоящей защитой, но выводит вас из-под оппортунистического сканирования.
- Ограничьте то, что вы получаете. Параметр
allowed_updatesпозволяет подписаться только на те типы обновлений, которые вы обрабатываете. Меньше поверхность, меньше парсинга. - Отвечайте быстро. Подтвердите получение запроса, а затем выполняйте работу асинхронно. Медленные обработчики вебхука, это отказ в обслуживании, который только и ждёт случая произойти.
3. Никогда не доверяйте содержимому обновления
Всё внутри обновления введено пользователем. Отображаемое имя, текст сообщения, данные callback при нажатии кнопки. Всё это, входные данные, контролируемые злоумышленником.
- Проверяйте данные callback на сервере. Кнопку с
order_id=123можно повторно отправить сorder_id=124. Проверьте, что нажавший пользователь действительно владеет этой записью. - Экранируйте пользовательский текст перед выводом. Если вы отправляете сообщения в режиме HTML или Markdown и вставляете отображаемое имя как есть, специально составленное имя может сломать форматирование или внедрить ссылку.
- Параметризуйте запросы к базе данных. Текст из чата, попадающий в строку запроса, несёт тот же риск инъекции, что и веб-форма.
- Ограничивайте принимаемые размеры. Установите лимиты на длину текста и размер файла до того, как начнёте что-либо обрабатывать.
4. Закройте админ-команды
Почти у каждого бота рано или поздно появляется админ-команда. Рассылка, возврат средств, экспорт пользователей. Именно здесь работающий бот превращается в инцидент.
- Проверяйте белый список ID пользователей на сервере, хранящийся в конфигурации. Никогда не определяйте статус администратора по имени пользователя, которое можно изменить и переиспользовать.
- Не прячьте, а проверяйте. Недокументированная команда обнаруживается в момент, когда её кто-то попробует. Скрытность не является контролем.
- Подтверждайте деструктивные действия вторым шагом и указывайте в тексте подтверждения, что именно сейчас произойдёт.
- Логируйте действия администратора с ID пользователя и меткой времени, чтобы потом можно было ответить на вопрос, кто отправил ту рассылку.
5. Включите режим приватности в группах
По умолчанию бот, добавленный в группу, получает только сообщения, которые являются командами, ответы на его собственные сообщения или упоминания его. Это поведение по умолчанию называется режимом приватности и существует не просто так.
Вы можете отключить его командой /setprivacy в BotFather, чтобы бот видел каждое сообщение в группе. Делайте это только если функция действительно этого требует. Как только он отключён, ваш сервер начинает хранить переписку других людей, и эта ответственность теперь лежит на вас.
6. Ограничивайте скорость для себя и для пользователей
Telegram применяет собственные лимиты, и их превышение приводит к троттлингу или временной блокировке. Общая рекомендация Telegram, около 30 сообщений в секунду в разные чаты и около 20 сообщений в минуту в один и тот же груп. Относитесь к этим значениям как к потолкам, до которых нужно оставлять запас, а не как к целям.
- Ставьте исходящие сообщения в очередь, а не отправляйте их в плотном цикле.
- Соблюдайте значение retry-after, когда API возвращает 429, вместо немедленного повтора.
- Ограничивайте также по каждому пользователю. Один человек, спамящий командой, не должен иметь возможность разгонять ваши расходы или исчерпывать вашу квоту.
- Устанавливайте задержку на всё дорогое, например на вызовы платной модели ИИ или на шаг генерации изображений.
7. Собирайте меньше пользовательских данных
Самая безопасная запись, та, которую вы никогда не сохраняли. Боты по умолчанию накапливают ID чатов, имена, номера телефонов и содержимое сообщений, и большая часть этого никогда не используется.
- Храните ID чата и то, что действительно нужно. Остальное пропускайте.
- Не логируйте полный текст сообщений, если у вас нет конкретной причины и срока хранения.
- Установите срок хранения и удаляйте данные по расписанию.
- Шифруйте чувствительные поля при хранении и ограничивайте, кто может обращаться к базе данных.
- Поддерживайте запросы на удаление. По GDPR и похожим законам пользователь может попросить удалить его данные, и у вас должен быть способ это сделать.
- Указывайте, что вы собираете, в политике конфиденциальности, на которую бот может дать ссылку.
Учтите, что номера телефонов доходят до вас только если пользователь нажимает кнопку запроса контакта. Запрашивать номер, который вам не нужен, это одновременно и потеря конверсии, и лишняя ответственность.
8. Проверяйте данные Web App и Login Widget
Если ваш бот открывает Telegram Web App или вы используете Login Widget на сайте, пользовательские данные приходят вместе с хешем. Проверьте этот хеш на своём сервере с помощью токена бота, прежде чем доверять хотя бы одному полю. Пропуск этой проверки означает, что кто угодно может выдать себя за любого пользователя, отредактировав запрос.
9. Следите и за скучными вещами
- Обновляйте зависимости. Большинство реальных компрометаций происходит через библиотеку, а не через сам Telegram.
- Ограничивайте, кто может деплоить и кто может читать продакшен-секреты.
- Следите за необычными паттернами: всплеск по одной команде, сообщения от одного пользователя в плотном цикле, запросы, не проходящие проверку секретного токена.
- Имейте план на плохой день. Отозвать токен, остановить вебхук, восстановиться из резервной копии. Запишите это заранее, до того как понадобится.
Чек-лист
- Токен живёт в переменных окружения, а не в git, и скрыт в логах.
- Вы знаете, как выполнить
/revokeв BotFather. - Вебхук использует HTTPS и секретный токен, который вы проверяете при каждом запросе.
allowed_updatesнастроен только на то, что вы обрабатываете.- Данные callback авторизуются на сервере, а не считаются доверенными в том виде, в котором пришли.
- Пользовательский текст экранируется перед выводом в отформатированном сообщении.
- Админ-команды проверяют белый список ID и логируются.
- Режим приватности включён, если только функция действительно не требует его отключения.
- Исходящие сообщения ставятся в очередь, а ответы 429 учитываются.
- Вы храните минимум, удаляете по расписанию и можете выполнить запрос на удаление.
- Payload Web App и Login Widget проверяются по хешу.
Пропустите то, что обычно идёт не так
В TeleMinute ваш токен хранится на сервере, вебхук управляется за вас, и у вас нет собственного сервера, который можно оставить открытым. Вы пишете диалог, мы управляем инфраструктурой.
Начните создавать уже сегодняЧитайте также
- Гайд по BotFather, включая то, как отозвать и заменить токен
- Лучшие практики для Telegram-ботов, более широкий чек-лист
- Лучшие практики UX для Telegram-ботов, для стороны дизайна
Часто задаваемые вопросы
Что произойдёт, если токен моего Telegram-бота утечёт?
Тот, у кого он окажется, получает полный контроль над ботом. Он сможет читать входящие сообщения, отправлять сообщения от вашего имени и изменить ваш вебхук так, что ваш собственный сервер перестанет получать обновления. Никакого запроса пароля на этом пути нет.
Как отозвать токен Telegram-бота?
Откройте BotFather, отправьте команду отзыва и выберите бота. Старый токен сразу перестаёт работать, и вы получаете новый. Переписывание истории git не помогает, потому что утёкший токен собирают за считаные минуты.
Видит ли мой бот все сообщения в группе?
Только если вы отключите режим приватности. По умолчанию бот в группе получает только команды, ответы на свои сообщения и прямые упоминания. Отключение режима приватности означает, что ваш сервер начинает хранить переписку других людей.
Нужен ли мне секретный токен для вебхука?
Да. Без него любой, кто найдёт URL вашего вебхука, сможет публиковать поддельные обновления, неотличимые от настоящего трафика Telegram. Задайте секрет при регистрации вебхука и отклоняйте запросы, у которых заголовок не совпадает.