История одной XSS в Telegram

Статья име­ет озна­коми­тель­ный харак­тер и пред­назна­чена для спе­циалис­тов по безопас­ности, про­водя­щих тес­тирова­ние в рам­ках кон­трак­та. Автор не несет ответс­твен­ности за любой вред, при­чинен­ный с при­мене­нием изло­жен­ной информа­ции. Рас­простра­нение вре­донос­ных прог­рамм, наруше­ние работы сис­тем и наруше­ние тай­ны перепис­ки прес­леду­ются по закону

Введение

Здравствуйте, уважаемые читатели Хабра! Сегодня я хочу поделиться с вами информацией о XSS-уязвимости, которую я обнаружил в Telegram около двух недель назад. Также статья коснется некоторых особенностей работы программы поиска уязвимостей от Telegram. Моя цель — не только продемонстрировать вам интересный и относительно простой пример XSS, но и обозначить причины, по которым, возможно, не стоит тратить свои усилия на участие в багбаунти программе Telegram.

Часть 1. XSS

В Telegram уже длительное время, по крайней мере с 2021 года, существовала возможность выполнения XSS-атаки на пользователя, исключительно в веб-версии приложения.

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

Click Me!

Разумеется, если мы отправим такую ссылку через Telegram, то не увидим ожидаемый результат:

9de5c599a245c7b578434c6c28bdf299.png

В связи с этим, я решил более тщательно изучить исходный код веб-клиента Telegram и обнаружил следующий фрагмент кода:

export function ensureProtocol(url?: string) {
  if (!url) {
    return undefined;
  }
  return url.includes('://') ? url : `http://${url}`;
}

Этот код проверяет наличие протокола в ссылках, приходящих в сообщениях, и если протокол отсутствует, автоматически добавляет 'http' в начало ссылки.

Такой подход к проверке является некорректным и определенно не соответствует RFC стандарту. Пример обхода данной проверки тривиален:

slonser.ru/#://

При отправке сообщения с такой ссылкой можно заметить, что веб-клиент не добавил http:// в начало ссылки. Следовательно, при нажатии на неё, пользователь будет перенаправлен на http://web.telegram.org/slonser.ru/#://.

Однако, если бы мы попытались вставить ссылку в следующем формате:

javascript:alert()/#://

Мы бы обнаружили, что наша ссылка не была корректно обработана. В чем же причина? Возможно, у Telegram есть черный список для некоторых ссылок? Или, возможно, они все-таки проверяют протокол javascript отдельно на серверной стороне? Ответ, разумеется, отрицательный! Дело в том, что символы »:» и »()» не являются допустимыми для доменных имен, и поэтому регулярное выражение на сервере не распознает это как ссылку.

На момент я задумался, решив, что попытка не удалась, и, возможно, Stored XSS в Telegram так и останется недостижимой мечтой. Однако, мне удалось довольно быстро придумать изящное решение:

javascript:alert@github.com/#://

Что же происходит в этом примере? Данная ссылка использует HTTP Basic Authentication, и серверная часть Telegram интерпретирует это как ссылку на github.com с данными аутентификации: username равным «javascript» и password равным «alert» (и в некотором смысле это верно). Как приятный дополнительный эффект, мы получаем превью нашей ссылки, которое выглядит как валидная ссылка на GitHub:

a4ce544077b68402d46374f67ffec893.png

Это существенно усиливает потенциальную угрозу от XSS-атаки, поскольку пользователи могут быть убеждены, что перед ними обычная ссылка на GitHub. Теперь осталось решить вопрос с символами, которые не допустимы в разделе username: password при парсинге. Решение заключается в использовании кодирования символов с помощью функции urlencode. Вот и финальный вариант :

javascript:alert%28%27Slonser%20was%20here%21%27%29%3B%2F%2F@github.com#;alert(10);://eow5kas78d0wlv0.m.pipedream.net%27

После нажатия на эту ссылку, мы увидим ожидаемый результат:

259442ed03910dc701c9aecf5f8bfeee.png

Часть 2. Impact

Рассмотрим, что же позволяет сделать данная уязвимость, например если отправить ссылку в крупный чат, то мы сможем от имени пострадавшего:

  1. Читать все сообщения пользователя, а также отправлять сообщения от его имени.

  2. Полностью захватить учетную запись пользователя, например, отправив запрос на установку нового пароля.

  3. Прочитать сообщения с кодами для входа в Telegram, которые приходят в приложение.

  4. Получить удаленное выполнение кода (RCE) в версии Telegram на платформе Electron! Да, вы не ослышались, посредством нажатия на специально сформированную ссылку, жертва может невольно предоставить злоумышленнику доступ к своему компьютеру.

Часть 3. Общение с Telegram Security

Хронология событий развивалась следующим образом:

  • 17 июня — отправил отчет о найденной уязвимости в Telegram, но не получил ответа.

  • 21 июня — обнаружил, что уязвимость была устранена, однако ответа от команды Telegram так и не последовало.

  • 24 июня — отправил запрос относительно статуса моего отчета о уязвимости. Ответа снова не последовало.

  • 26 июня — благодаря связям через знакомых, смог напрямую связаться с командой безопасности Telegram. Получил ответ:

    Hello,

    Thank you for your email. We will send you an update soon.

    All the best,Telegram Support

  • 27 июня — получил сообщение: Thank you for your report. We would like to award you a bounty of XXXX euro for your findings.

Я специально скрыл сумму вознаграждения, чтобы проверить детективные навыки читателей этой статьи. В качестве подсказки: программа багбаунти Reddit, которая имеет схожие условия (с максимальной выплатой в приложении 10 тыс. долларов, как и у Telegram), предоставила 5 тыс. долларов за аналогичную проблему.

Итак, сколько же мне выплатили?

Ответ

500 евро.

Считаю ли я эту сумму справедливой? — Нет.

Вправе ли Telegram так поступать? — Да, безусловно. У них нет четкой градации уязвимостей и соответствующих выплат на их платформе багбаунти.

Каковы мои впечатления? — Негативные. Создается впечатление, что Telegram не особо заинтересован в обеспечении своей безопасности. Я не уверен, что стоит заниматься поиском уязвимостей ради такого опыта.

Part Final. Выводы

Мои выводы следующие:

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

  2. К сожалению, программа багбаунти от Telegram оставляет желать лучшего. Отсутствует четкая градация уязвимостей, поддержка не всегда отвечает на обращения, а справедливость выплат вызывает сомнения.

Надеюсь, эта статья была полезной для вас. Жду ваших комментариев!

© Habrahabr.ru