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

Хранимая Xss-уязвимость в telegram desktop: детали после исправления

# Telegram попросил не публиковать сведения об XSS. Мы раскрываем детали после исправления

Хранимая XSS-уязвимость в Telegram Desktop позволяла спрятать JavaScript в inline-кнопке сообщения. Вредоносный код мог месяцами оставаться незаметным, а затем запускаться при открытии HTML-экспорта переписки. При этом боту не требовалось состоять в чате: достаточно было, чтобы кто-то переслал туда подготовленное сообщение.

Мы сообщили о проблеме Telegram 3 июня 2026 года. В июле компания выпустила исправление, однако не одобрила публикацию материала. Поскольку уязвимость уже была закрыта, мы отказались от вознаграждения и предложили направить его на благотворительность. Также просили согласовать дату раскрытия. Этот текст - итоговое описание проблемы. Рабочий эксплойт и данные атакуемых систем не публикуются.

## Как выглядела атака

Представим инженерный чат финтех-компании. Раз в полгода его экспортируют для внутренней проверки. Сотрудник открывает Telegram Desktop, выбирает "Экспорт истории чата", сохраняет переписку в HTML и запускает получившийся файл в браузере.

В архиве могут находиться имена сотрудников, сообщения, фрагменты исходного кода, внутренние обсуждения и случайно опубликованные секреты - например AWS-ключ, который кто-то отправил "на минуту".

Пользователь видит обычную страницу с перепиской. Однако в одном из сообщений уже может находиться вредоносная inline-кнопка. Во время формирования HTML встроенный скрипт выполняется автоматически, без дополнительного нажатия. Он получает доступ к содержимому открытой страницы, собирает сообщения и может отправить их на внешний сервер.

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

## Почему бот мог не состоять в группе

Сценарий начинался с создания обычного Telegram-бота. Bot API позволяет добавлять к сообщениям inline-клавиатуры, а текст кнопки может содержать произвольные символы Unicode. В частности, в него можно было поместить HTML-конструкцию.

Клавиатура, состоящая только из URL-кнопок, сохранялась при пересылке благодаря механизму `CopyMarkupToForward`. Поэтому бот мог отправить сообщение в личный чат или другой канал, после чего любой пользователь пересылал его в нужную группу. Боту не требовалось получать доступ к истории, видеть участников или самостоятельно вступать в обсуждение.

Полученное сообщение становилось своеобразным контейнером для вредоносной разметки. Пока его просто читали в Telegram, код не выполнялся. Опасность возникала позже - при экспорте переписки в HTML.

## Техническая причина

В Telegram Desktop сообщения перед сохранением в HTML проходят экранирование. Функция `SerializeString()` преобразует специальные символы `<`, `>`, `&`, кавычки и апострофы в безопасные HTML-сущности. Она также обрабатывает переводы строк, Unicode-разделители и управляющие ASCII-символы.

Такая же защита применялась к именам отправителей и другим полям. Но текст inline-кнопок обрабатывался иначе. В файле `export_output_html.cpp` соответствующее значение напрямую записывалось в формируемую страницу. Поэтому HTML в поле `text` кнопки оставался активной разметкой.

Если в этом поле находился тег `

Прокрутить вверх