
Начиная с 23.03.2022 16:20:08 UTC+8, злоумышленник эксплуатировал уязвимость CashioApp, опустошив счёт залоговых токенов и причинив ущерб примерно в 52 млн. Атака стала возможной из-за недостаточной проверки входных аккаунтов, которая позволила злоумышленнику выпустить 20 млрд токенов $CASH без внесения каких-либо средств. Ниже мы приводим технические подробности.
Краткое изложение
Причиной инцидента стала ошибка в программе Brrr, предназначенной для выпуска и сжигания токенов $CASH под залог LP-токенов Saber Arrow. В частности, пользователи могут выпускать $CASH, то есть создавать токены $CASH, внося LP-токены Arrow. Отметим, что базовыми токенами LP-токена Arrow служат LP-токены Saber. Инструкция print_cash, позволяющая выпускать $CASH, принимает список аккаунтов, включая аккаунты Bank и Collateral. Они используются для учёта и отслеживания залога (то есть LP-токенов Arrow), который разрешено использовать для выпуска $CASH. По замыслу эти два аккаунта должны инициализироваться и авторизоваться только администратором. Однако программа не проверяет действительность аккаунта Bank. В результате злоумышленник может создать ряд поддельных аккаунтов (включая аккаунт Bank), передать их инструкции print_cash и выпустить $CASH почти бесплатно (затратив средства лишь на комиссии за транзакции).
Подробности
Начнём анализ с аккаунтов, используемых инструкцией print_cash, которые показаны ниже.


Атрибут common (строка 75) представляет собой структуру, тип которой в программе — BrrrCommon. В BrrrCommon аккаунты bank и collateral инициализируются и авторизуются администратором. crate_token — это аккаунт токена $CASH, в котором хранится информация о $CASH, в том числе публичный ключ crate_mint (строка 107), публичные ключи административных ролей и другие сведения. crate_collateral_tokens — это аккаунт-хранилище залоговых токенов, переведённых пользователями. Поскольку залогом должны служить LP-токены Arrow, базовыми токенами которых являются LP-токены Saber, пользователи должны указать связанные аккаунты saber_swap. Последние два атрибута структуры BrrrCommon — это идентификаторы целевых программ, используемых в инструкции. Отметим, что последние четыре атрибута структуры PrintCash — это системный аккаунт пользователя (который также подписывает транзакцию), залоговый аккаунт пользователя, аккаунт пользователя для токенов $CASH, получающий выпущенные токены $CASH, и публичный ключ аккаунта, уполномоченного выпускать $CASH.
Атакующая транзакция
Разобравшись с назначением перечисленных аккаунтов, перейдём к анализу атакующей транзакции: 0x4fgL…z2K5. Эта атака инициирована с адреса злоумышленника (показан как 0x6D7f); список входных аккаунтов инструкции PrintCash приведён ниже.

Приведённый выше Account #1 (0x5aha) соответствует аккаунту Bank. Мы заметили, что он отличается от адреса, указанного на официальном сайте CashioApp (0xEm1P). Это означает, что проверка аккаунта Bank недостаточна!
Проверка
Рассмотрим подробнее проверку структуры BrrrCommon в коде, чтобы выяснить, как её удалось обойти.

Единственная проверка входного аккаунта Bank — проверка того, что переданный аккаунт Collateral связан с аккаунтом Bank (строка 12). Однако её легко обойти, если также предоставить поддельный аккаунт Collateral. Кроме того, чтобы не вносить реальные залоговые активы, злоумышленник предоставил и поддельные аккаунты saber_swap. Отметим, что злоумышленник стремится внести не имеющие ценности залоговые активы, чтобы выпустить ценные токены $CASH, поэтому предоставленные им адреса crate_token и crate_mint должны быть настоящими. Иными словами, недостаточная проверка аккаунта Bank позволяет злоумышленнику создать ряд поддельных аккаунтов для выпуска $CASH под не имеющий ценности залог.
Исправление

Исправление заключается в добавлении выражения assert_keys_eq!(self.bank.crate_mint, self.crate_mint). Оно гарантирует, что значение crate_mint в аккаунте Bank является правильным crate_mint для $CASH. Но как это гарантирует действительность аккаунта Bank? Чтобы найти ответ, рассмотрим структуру NewBank (в программе bankman) и структуру NewCrate (в программе crate_token).


На самом деле аккаунт Bank — это PDA, в состав сидов которого входит адрес crate_token. При этом crate_token также является PDA, в состав сидов которого входит адрес crate_mint. Это гарантирует действительность аккаунта Bank, если переданный crate_mint действителен. Без правильного crate_mint злоумышленники не могут выпустить $CASH и провести атаки.
О BlockSec
BlockSec — передовая компания в области безопасности блокчейна, основанная в 2021 году группой признанных во всём мире экспертов по безопасности. Компания стремится повысить безопасность и удобство использования формирующегося мира Web3, чтобы способствовать его массовому распространению. Для этого BlockSec предоставляет услуги аудита безопасности смарт-контрактов и блокчейнов EVM, платформу Phalcon Security для разработки с учётом безопасности и упреждающей блокировки угроз, платформу MetaSleuth для отслеживания средств и проведения расследований, а также расширение MetaSuites, помогающее разработчикам Web3 эффективно ориентироваться в мире криптовалют.
На сегодняшний день компания обслужила более 300 известных клиентов, среди которых MetaMask, Uniswap Foundation, Compound, Forta и PancakeSwap, и привлекла десятки миллионов долларов США за два раунда финансирования от ведущих инвесторов, включая Matrix Partners, Vitalbridge Capital и Fenbushi Capital.
Официальный сайт: https://blocksec.com/
Официальный аккаунт в Twitter: https://twitter.com/BlockSecTeam



