
A partir de 23/03/2022 16:20:08 UTC+8, a CashioApp foi explorada para esvaziar a conta de tokens de garantia, causando uma perda de aproximadamente 52 milhões. O ataque foi possível devido à verificação insuficiente das contas fornecidas como entrada, que permitiu ao invasor cunhar 20 bilhões de tokens $CASH sem fazer nenhum depósito. A seguir, apresentamos os detalhes técnicos.
Resumo
O incidente ocorreu devido a um bug no programa Brrr, projetado para gerenciar a cunhagem e a queima de tokens $CASH com Saber LP Arrows como garantia. Especificamente, os usuários podem emitir $CASH, ou seja, cunhar $CASH, depositando tokens LP Arrow. Observe que o token LP Arrow recebe o token LP Saber como token subjacente. A instrução print_cash, que pode cunhar $CASH, recebe uma lista de contas que inclui a conta Bank e a conta Collateral. Essas contas são usadas para registrar e acompanhar a garantia (isto é, tokens LP Arrow) que pode ser utilizada para cunhar $CASH. Por definição, essas duas contas deveriam ser inicializadas e autorizadas apenas pelo administrador. No entanto, o programa não verifica a validade da conta Bank. Assim, o invasor pode criar uma série de contas falsas (incluindo a conta Bank) para fornecê-las à instrução print_cash e emitir $CASH praticamente de graça (o único custo são as taxas de transação).
Detalhes
Vamos começar a análise pelas contas usadas na instrução print_cash abaixo.


O atributo common (linha 75) é uma estrutura do tipo BrrrCommon no programa. Em BrrrCommon, a conta bank e a conta collateral são inicializadas e autorizadas pelo administrador. O crate_token é a conta do token $CASH, que armazena informações sobre $CASH, como a chave pública de crate_mint (linha 107), as chaves públicas dos papéis de administrador, entre outras. O crate_collateral_tokens é uma conta-cofre que mantém os tokens de garantia transferidos pelos usuários. Como a garantia deve consistir em tokens LP Arrow, que recebem os tokens LP de Saber, os usuários precisam fornecer as contas relacionadas a saber_swap. Os dois últimos atributos da estrutura BrrrCommon são IDs dos programas-alvo usados na instrução. Observe que os quatro últimos atributos da estrutura PrintCash são a conta de sistema do usuário (que também assina a transação), a conta de garantia do usuário, a conta de tokens $CASH do usuário, que recebe os $CASH cunhados, e a chave pública da conta que tem autoridade para cunhar $CASH.
A transação do ataque
Após entender a função das contas acima, passamos a analisar a transação do ataque: 0x4fgL…z2K5. Esse ataque foi iniciado a partir do endereço do invasor (localizado em 0x6D7f), e a lista de contas fornecidas como entrada à instrução PrintCash é mostrada abaixo.

O Account #1 (0x5aha) acima corresponde à conta Bank. Observamos que ele difere do endereço fornecido no site oficial da CashioApp (0xEm1P), o que significa que a validação da conta Bank é insuficiente!
Validação
Vamos examinar mais de perto a validação da estrutura BrrrCommon no código para entender como ela é contornada.

A única verificação da conta Bank fornecida como entrada é garantir que a conta Collateral fornecida como entrada esteja associada à conta Bank (linha 12). No entanto, essa verificação pode ser facilmente contornada fornecendo também uma conta Collateral falsa. Além disso, para evitar pagar com ativos de garantia reais, o invasor também forneceu contas saber_swap falsas. Observe que o objetivo do invasor é depositar ativos de garantia sem valor para emitir tokens $CASH valiosos; por isso, os endereços de crate_token e crate_mint fornecidos pelo invasor devem ser verdadeiros. Em outras palavras, a verificação insuficiente da conta Bank permite ao invasor criar uma série de contas falsas para emitir $CASH com uma garantia sem valor.
A correção

A correção consiste em adicionar a instrução assert_keys_eq!(self.bank.crate_mint, self.crate_mint). Ela garante que o crate_mint da conta Bank seja o crate_mint correto para $CASH. Mas como isso garante que a conta Bank seja válida? Vamos examinar a estrutura NewBank (no programa bankman) e a estrutura NewCrate (no programa crate_token) para encontrar a resposta.


Na verdade, a conta Bank é uma PDA cujas seeds contêm o endereço de crate_token. Por sua vez, o crate_token também é uma PDA cujas seeds contêm o endereço de crate_mint. Isso garante que a conta Bank seja válida se o crate_mint fornecido como entrada for válido. Sem um crate_mint correto, os invasores não conseguem cunhar $CASH nem executar os ataques.
Sobre a BlockSec
A BlockSec é uma empresa pioneira em segurança de blockchain, fundada em 2021 por um grupo de especialistas em segurança de renome mundial. A empresa se dedica a melhorar a segurança e a usabilidade do mundo emergente da Web3 para facilitar sua adoção em massa. Para isso, a BlockSec oferece serviços de auditoria de segurança de contratos inteligentes e cadeias EVM, a plataforma Phalcon Security para desenvolvimento seguro e bloqueio proativo de ameaças, a plataforma MetaSleuth para rastreamento de fundos e investigação, e a extensão MetaSuites para que desenvolvedores web3 naveguem com eficiência pelo mundo cripto.
Até o momento, a empresa atendeu mais de 300 clientes de prestígio, como MetaMask, Uniswap Foundation, Compound, Forta e PancakeSwap, e recebeu dezenas de milhões de dólares americanos em duas rodadas de financiamento de investidores de destaque, incluindo Matrix Partners, Vitalbridge Capital e Fenbushi Capital.
Site oficial: https://blocksec.com/
Conta oficial no Twitter: https://twitter.com/BlockSecTeam



