
23 марта 2022 года в 16:20:08 (UTC+8) проект CashioApp подвергся эксплойту, в результате которого с аккаунтов обеспечения было выведено около 52 миллионов долларов. Хакерская атака стала возможной из-за недостаточной проверки входящих аккаунтов, что позволило злоумышленнику выпустить (минтить) 20 миллиардов токенов $CASH без какого-либо депозита. Ниже мы приводим технические подробности.
Резюме
Инцидент произошел из-за ошибки в программе Brrr, которая предназначена для управления выпуском (минтингом) и сжиганием токенов $CASH под обеспечение Saber LP Arrows. В частности, пользователи могут печатать $CASH, то есть выпускать $CASH, внося LP-токены Arrow. Обратите внимание, что LP-токены Arrow получают Saber LP-токен в качестве базовых токенов. Инструкция 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 являются идентификаторами программ (program ID), используемых в инструкции. Обратите внимание, что последние четыре атрибута в структуре PrintCash — это системный аккаунт пользователя (также подписант транзакции), аккаунт обеспечения пользователя, аккаунт токена $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, семена (seeds) которого содержат адрес crate_token. В то же время crate_token также является PDA, семена которого содержат адрес crate_mint. Это гарантирует, что аккаунт Bank действителен, если входящий crate_mint действителен. Без корректного crate_mint злоумышленники не могут выпустить $CASH и осуществить атаку.
О компании BlockSec
BlockSec — передовая компания в сфере блокчейн-безопасности, основанная в 2021 году группой экспертов мирового уровня. Компания стремится повысить безопасность и удобство использования развивающегося мира Web3, чтобы способствовать его массовому внедрению. С этой целью BlockSec предоставляет услуги аудита безопасности смарт-контрактов и EVM-цепей, платформу Phalcon для разработки систем безопасности и проактивного блокирования угроз, платформу MetaSleuth для отслеживания и расследования транзакций, а также расширение MetaSuites для эффективной работы Web3-разработчиков в криптомире.
На сегодняшний день компания обслужила более 300 уважаемых клиентов, таких как MetaMask, Uniswap Foundation, Compound, Forta и PancakeSwap, и получила десятки миллионов долларов США в рамках двух раундов финансирования от ведущих инвесторов, включая Matrix Partners, Vitalbridge Capital и Fenbushi Capital.
Официальный сайт: https://blocksec.com/
Официальный аккаунт в Twitter: https://twitter.com/BlockSecTeam



