Пользователь торговой платформы Fomo лишился примерно 48 тысяч долларов. При этом он не подключал кошелёк, не подписывал разрешений и не вводил секретную фразу. Деньги ушли после того, как он прошёл "проверку на человека" на стороннем сайте. Проверка оказалась поддельной: жертву уговорили добавить в браузер закладку с вредоносным кодом и запустить её на странице, где он уже был авторизован. Случай показывает, что для кражи средств из встроенного кошелька злоумышленникам не нужны ни подпись транзакции, ни приватный ключ. Достаточно доступа к учётной записи сервиса, через которую открывается кошелёк.
Описание
Инцидент начался со страницы токена MOONLET. На площадке Fomo рядом с названием актива и в разделе с описанием проекта есть ссылки на внешний сайт. Пользователь нажал одну из них и попал на ресурс, оформленный как страница торгового продукта. Там ему показали девять иконок и предложили найти среди них четвероногое животное. Затем следовала инструкция: перетащить найденный значок в панель закладок браузера и трижды по нему щёлкнуть. Со стороны это выглядело как обычная проверка, подтверждающая, что действие выполняет человек, а не программа. Дополнительно сайт показывал торговый терминал с имитацией рыночных данных и неработающей кнопкой подключения кошелька. Всё это нужно было только для правдоподобия.
Анализ SlowMist показал, что перетаскиваемая закладка не содержала адреса сайта. Вместо ссылки в неё был встроен код, который браузер запускает прямо на открытой странице. Выбор животного ни на что не влиял: все девять значков вели к одному и тому же коду. Уловка с "поиском животного" служила лишь поводом передать пользователю вредоносную закладку. Код подменял содержимое закладок на странице многократно: при изменениях страницы, по таймеру, при нажатии кнопки мыши и в начале перетаскивания. Похожий приём прежде применяли против участников сообществ в Discord, когда закладка воровала токены доступа.
Когда жертва нажимала закладку на странице Fomo, код проверял, что открыт нужный ресурс, и начинал читать данные, которые браузер хранит для этой страницы. Его интересовали записи, связанные со входом в аккаунт и с кошельком: токены доступа, токены обновления сессии, а также всё, что содержало слова о кошельке, секретах и ключах. Отдельно код просматривал внутреннюю базу браузера, куда веб-приложения складывают структурированные данные, и вытаскивал оттуда записи о сессиях и восстановлении доступа. На каждый шаг отводилось ограниченное время, чтобы ни один сбор не завис. Собранную информацию код упаковывал, при необходимости сокращал и отправлял на внешний сервер, после чего возвращал пользователя обратно на страницу с "проверкой".
Отдельная часть кода отвечала за двухфакторную аутентификацию. Сначала она проверяла, привязан ли к аккаунту хотя бы один дополнительный способ подтверждения входа. Если да, код пытался добавить новый способ - одноразовые коды, которые меняются каждые 30 секунд. Для этого он получал секретную строку для генерации таких кодов и подтверждал привязку от имени пользователя. У жертвы двухфакторная аутентификация включена не была, поэтому эта ветка, скорее всего, не сработала. На сбор и отправку данных это никак не повлияло: они шли независимыми каналами.
Полученные токены дают доступ к аккаунту и к встроенному кошельку, который платформа создаёт для пользователя. Через них можно восстановить управление кошельком, добраться до ключей и инициировать переводы. Именно поэтому отказ от ввода секретной фразы и от подписи транзакций не защищает от потери средств. Встроенный кошелёк живёт внутри сервиса, и его безопасность напрямую зависит от сохранности учётных данных в браузере. Точный путь, которым в итоге вывели деньги, ещё предстоит подтвердить по журналам сервера и записям в блокчейне.
Дальнейший анализ движения средств провели с помощью MistTrack, инструмента той же компании для отслеживания транзакций. Сведения о риске оперативно разошлись по каналам оповещения клиентов системы мониторинга. Сообщается, что всего было выведено 45 106,85 USDC тремя переводами. Кошелёк злоумышленника активизировался 17 сентября, и до поступления денег жертвы через него уже проходили обмены USDC на SOL и обратно сопоставимыми суммами. Это указывает на возможных других пострадавших. Полученные средства дробили, меняли на другие активы и разводили по множеству промежуточных адресов. Часть денег переводили в другие сети, обменивая SOL на ETH и BTC. Крупнейшим каналом вывода стал сервис для анонимных переводов, куда ушло 1 568,33 SOL. Ещё часть средств поступила на адреса, связанные с игорными платформами Stake и Winna.
Обычная проверка на человека не требует перетаскивать значки в панель закладок и нажимать их на страницах с кошельком или биржей. Столкнувшись с таким предложением, стоит сразу закрыть сайт. Полезно время от времени просматривать панель закладок и удалять незнакомые, особенно те, что начинаются не с адреса сайта, а с кода. Для аккаунтов, где это поддерживается, нужно включать многофакторную аутентификацию. Тем, кто уже запустил подозрительную закладку, стоит зайти в сервис с доверенного устройства, отозвать посторонние сессии и лишние разрешения, проверить список подключённых приложений и подтверждений входа. Если есть подозрение, что секретная фраза или ключ попали к посторонним, остатки средств лучше перевести на новый кошелёк. Проектам стоит требовать отдельного подтверждения для смены способов двухфакторной аутентификации и вывода средств, показывать пользователю активные сессии и оповещать о подозрительных входах.
