Это было в октябре 2020 года, когда я по понятным причинам застрял дома и, имея массу свободного времени, страдал от безделья. Чтобы как-то развлечься, решил заняться мозговым штурмом: вспомнил былое хобби — белый хакинг, который я забросил из-за отсутствия времени.

В 2016 году я нашел уязвимость в библиотеке OAuth и теперь надеялся найти подобную интересную задачку. Поскольку я ежедневно пользуюсь WhatsApp, подумал, что с таким же успехом мог бы взломать WhatsApp.

День 1-й

Первоначальная идея состояла в том, чтобы протестировать XSS (cross-site scripting — межсайтовое выполнение сценариев) в системе обмена сообщениями. WhatsApp в мобильных и веб-версиях поддерживает функции сложного текста, такие как жирный шрифт, курсив, изображения и списки, так что моя затея выглядела многообещающе. Много лет назад у большинства веб-приложений были XSS-уязвимости, однако с появлением таких фреймворков, как ReactJS, они стали встречаться реже. Я открыл WhatsApp на мобильном телефоне, а также в браузере и начал отправлять себе сообщения, надеясь на интересные результаты. Отладка в веб-версии WhatsApp, работавшей с Chrome Devtools «из коробки», была намного проще.

Я попытался добиться сбоев в работе UI, вставив некоторые фрагменты HTML и JavaScript, как показано ниже. Я не стремился получить доступ к какому-либо аккаунту. Моей целью было просто нарушить что-нибудь, увидеть ошибку в консоли или неработающий UI. Это был бы верный признак того, что я двигаюсь в правильном направлении.

':;"><h1>XSS
`'"});
//]]!> -->

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

К сожалению, безуспешно.

День 2-й

Я был немного разочарован полным отсутствием результатов, но не растерял мотивацию. Заметил в WhatsApp удобную функцию превью веб-страницы, на которую пользователь отправляет кому-нибудь ссылку. Нельзя ли использовать XSS-уязвимость в этом превью?

Я быстро настроил свой сервер на PHP. Да, вы правильно прочитали: PHP. Около 1000 компаний предоставляют бесплатный хостинг для PHP, но не так много предлагают услуги бесплатного хостинга для NodeJS, да и не было необходимости прибегать к работе с Docker. Сервер был очень простым и создавался только для отладки функции предпросмотра ссылок в WhatsApp. Представьте что-то вроде этого:

<?php

echo "<meta name=\"title\" value=\"{$_GET['title']}\" />";
echo "<meta name=\"description\" value=\"{$_GET['description']}\" />";
echo "<meta name=\"keywords\" value=\"{$_GET['keywords']}\" />";
// и так далее

Когда сервер был запущен, я начал отправлять себе сообщения со ссылками (типа https://example.com?title=‘“;”><h1>XSS), надеясь на какой-нибудь сбой и вывод больших букв XSS.

К сожалению, после многочисленных попыток удача снова оказалась не на моей стороне.

День 3-й

На третий день я уже мало на что надеялся. Просто перебирал и проверял различные функции WhatsApp, подспудно размышляя над тем, чем мог бы воспользоваться злоумышленник. Протестировал превью сообщений, gif-файлы, эмодзи, загрузку файлов и их предварительный просмотр… Копаясь, обратил внимание на аватарки. С изображениями мало что можно сделать, верно? Посмотрел, откуда берутся аватарки, и заметил, что, вероятно, по соображениям производительности, запущен сервис-воркер, который позволяет уменьшать масштаб аватарок.

В списке контактов аватарка уменьшается, полное изображение можно увидеть только при открытии подробной информации о пользователе. С изображениями профилей все было в порядке, но, поскольку в WhatsApp работал сервис-воркер, у меня появился дополнительный файл, который можно было проверить с точки зрения уязвимости.

Я заметил интересный механизм кэширования. Предполагаю, что он используется для сохранения некоторых данных и избежания сетевых запросов, когда они не нужны. Сервис-воркер — подходящий для реализации подобной логики слой. Как он работает?

Для примера возьмем следующий URL: https://web.whatsapp.com/pp?e=https://web.whatsapp.com/image-profile-1.jpg&t=1&u=1&i=1&n=1.

При первом посещении этого URL получаем изображение из интернета, а при повторном — кэшированную версию, предоставляемую сервис-воркером.

Немного покопавшись, я заметил, что механизм кэширования работает не только для изображений, но и для любых файлов. Если бы я только мог поместить свой вредоносный URL в параметр e, а затем сделать так, чтобы WhatsApp отображал HTML с моего сайта, это была бы победа! Однако возникла одна загвоздка: параметр e не мог быть любым URL — только URL, внесенным в белый список в заголовке content-security-policy.

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

В качестве последней попытки я попробовал вставить URL data: в параметр e, и, к моему удивлению, контент в URL data: отобразился.

Что такое URL data:? Представьте URL, который выглядит следующим образом — data:text/html,<h1>hello</h1>. Для кого-то это может показаться не совсем корректным URL, но такие URL поддерживаются многими современными браузерами. Если вы скопируете этот URL и вставите его в браузер, то увидите заголовок с приветствием hello.

Далее я создал URL с тегом <script>, выполняющим alert(1), чтобы убедиться в наличии XSS-уязвимости. URL выглядел следующим образом:

Https://web.whatsapp.com/pp?e=data:text/html,<script>alert(1)</script>&t=1&u=1&i=1&n=1 

Открыв URL, увидел милое предупреждение с цифрой 1, что было достаточно убедительным доказательством наличия XSS-уязвимости.

Я быстро описал все шаги по устранению уязвимости и отправил запрос в службу поддержки. В субботу, 31 октября 2020 года, сообщил о проблеме, а в понедельник, 2 ноября 2020 года, уже получил сообщение о том, что проблема устранена. Меня попросили подтвердить факт устранения проблемы, что я и сделал. В понедельник, 7 декабря 2020 года, я получил награду за исправление ошибки.

Потенциальное влияние уязвимости

При использовании XSS-уязвимости злоумышленник обычно получает полный доступ к вашему аккаунту на время сессии (если только он не решит перехватить вашу сессию — что в одних случаях возможно, а в других нет). Если злоумышленник отправит вам ссылку и вы нажмете на нее, он сможет читать все ваши сообщения, отправлять сообщения от вашего имени и просматривать список ваших контактов.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Michal Szorad: How I Hacked WhatsApp Web in 3 Days

Предыдущая статьяEncore.ts — в 9 раз быстрее Express.js и в 3 раза быстрее Bun + Zod
Следующая статья5 навыков работы в Python на прокачку