Stored XSS в Telegram Desktop: от текста кнопки до JavaScript в экспорте — 17 сентября 2026 г. в 10:49:16.017
Stored XSS в Telegram Desktop: от текста кнопки до JavaScript в экспорте ExPatch разобрали XSS в HTML-экспорте Telegram Desktop. Источник недоверенных данных — поле text inline-кнопки бота. Экспортёр записывал его в HTML без экранирования: // Было block.append(button.text.toUtf8()); // Исправление block.append(SerializeString(button.text.toUtf8())); toUtf8() меняет кодировку, но не обезвреживает HTML. Поэтому <script> внутри подписи кнопки становился исполняемой разметкой. Для текста сообщений экранирование уже применялось; отдельный путь сериализации кнопок его пропускал. Доставка шла через штатный Bot API: sendMessage → reply_markup.inline_keyboard → text. Клавиатура с URL-кнопкой сохранялась при пересылке через CopyMarkupToForward. Участник мог перенести сообщение в группу, где самого бота никогда не было. В демонстрации символы U+3164 перед тегом маскировали его в интерфейсе клиента. Условие срабатывания: пользователь экспортирует историю уязвимой сборкой и открывает HTML-страницу, содержащую это сообщение. JavaScript запускается при загрузке, без нажатия кнопки. Доступен DOM открытого документа: тексты, отправители, временные метки. Возможны отправка данных наружу, подмена отображаемой истории и фишинговая форма. Чтение соседних страниц экспорта или произвольных файлов этим PoC не подтверждено; серверная переписка не меняется. Тот же патч исправляет инъекцию в JS-строку внутри onclick="return ShowTextCopied('…')": перед подстановкой содержимого экранируются обратная косая черта и одинарная кавычка. Здесь уже нужен учёт контекста JavaScript. Исправление вошло в Beta 6.9.4 и stable 7.0.1. Старые HTML-файлы обновление клиента не переписывает: их нужно экспортировать заново исправленной версией либо открывать с отключённым JavaScript. @poxek | @poxek_ai | MAX