Back to Blog

Análise do Incidente de Segurança do Indexed Finance

Code Auditing
October 22, 2021
7 min read

0x.1 Contexto

Em 02:38 (UTC+8) do dia 15 de outubro de 2021, nosso sistema interno de monitoramento detectou transações suspeitas de flashloan:

Nosso sistema de monitoramento
Nosso sistema de monitoramento

Após investigação, descobrimos que se tratava de um ataque de manipulação de preços direcionado ao Indexed Finance. Especificamente, o atacante lançou o ataque explorando uma fórmula falha (utilizada para calcular o preço) deste projeto, obtendo um lucro de $16 milhões.

Já existem algumas discussões nas redes sociais, enquanto o projeto publicou um post-mortem oficial (Indexed Attack Post-Mortem). No entanto, as análises existentes não oferecem uma compreensão completa deste incidente de segurança. Portanto, neste blog, nosso objetivo é fornecer uma análise abrangente, incluindo o mecanismo do projeto, a vulnerabilidade, o ataque e o lucro.

0x1.1 Endereços de Contratos Relevantes

  • MarketCapSqrtController: 0x120c6956d292b800a835cb935c9dd326bdb4e011

  • DEFI5: 0xfa6de2697d59e88ed7fc4dfe5a33dac43565ea41

  • CC10: 0x17ac188e09a7890a1844e5e65471fe8b0ccfadf3

0x1.2 Transações do Ataque

  • TX-I do Ataque: 0x44aad3b853866468161735496a5d9cc961ce5aa872924c5d78673076b1cd95aa

  • TX-II do Ataque: 0xbde4521c5ac08d0033019993b0e7e1d29b1457e80e7743d318a3c27649ca4417

0x2. Mecanismo do Indexed Finance

Para melhor compreender a vulnerabilidade/ataque, utilizamos o DEFI5 (ou seja, o pool hackeado pelo atacante) para demonstrar o mecanismo do Indexed Finance.

0x2.1 Vinculação de Token

O DEFI5 foi projetado para fornecer serviço de negociação para os 5 principais tokens de projetos DeFi do Ethereum. Especificamente, o Indexed Finance atualiza o ranking dos tokens com base em sua capitalização de mercado através do MarketCapSqrtController. Como a classificação dos 5 principais tokens pode mudar com o tempo, o número de tokens utilizados pelo pool DEFI5 pode ser maior que 5, conforme mostrado no seguinte código:

Figura 1
Figura 1

A Figura 1 mostra que, para vincular um novo token, o DEFI5 deve acionar a função _bind invocada pela função reindexTokens, que só pode ser invocada pela função reindexPools do MarketCapSqrtController:

Figura 2
Figura 2

A Figura 2 demonstra que o MarketCapSqrtController primeiro busca informações do token (incluindo o TotalSupply e o preço) nos mercados, e então calcula o ranking com base em sua capitalização de mercado. Ao invocar a função reindexPool, os endereços dos principais tokens serão passados como argumentos para invocar a função reindexTokens. Note que o novo token adicionado será vinculado ao DEFI5 sem substituir os tokens originais do DEFI5.

0x2.2 O Que Vem a Seguir?

Após a vinculação do token, o DEFI5 deve definir uma variável chamada ready (que indica o status do token) como true para habilitar a negociação:

Figura 3
Figura 3

De acordo com a lógica do código, além da inicialização do contrato, o ready só pode ser definido na função gulp. Conforme mostrado na Figura 3, isso ocorre quando o saldo do token no DEFI5 é maior ou igual a _minimumBalances. Enquanto isso, o peso inicial do token (ou seja, denorm) será calculado com base na seguinte fórmula:

0x3. Análise da Vulnerabilidade

O código vulnerável pertence à função updateMinimumBalance do MarketCapSqrtController.

Figura 4
Figura 4

Conforme mostrado na Figura 4, updateMinimumBalance pode alterar o minimumBalance de um token cujo ready é false para 1/100 do poolValue. O cálculo do poolValue é a chave da vulnerabilidade.

Figura 5
Figura 5

O cálculo da Figura 5 apenas implementa a seguinte fórmula:

No entanto, existem dois problemas potenciais nessa fórmula:

  • utilizar a liquidez de um token para estimar o valor de todo o pool;
  • os pesos do pool (_totalWeight) e do token (token.denorm) não são afetados pela mudança de liquidez. Na prática, eles são influenciados pela Capitalização de Mercado dos mercados externos. Além disso, sua variação é limitada pelo período de tempo, ou seja, aumento ou diminuição de 1% por hora.

Em resumo, o atacante é capaz de manipular o poolValue utilizando o flashloan para causar instantaneamente uma grande mudança na liquidez de um token, enquanto os pesos do pool e do token permanecem inalterados. Ao fazer isso, o minimumBalance do token (cujo ready é false) pode ser manipulado para lançar o ataque de manipulação de preços.

0x4. Análise do Ataque

O ataque consiste nas seguintes 9 etapas:

Etapa 1: invocar a função reindexPool para vincular SUSHI. Antes da invocação, há 6 tokens no pool DEFI5, incluindo UNI, AAVE, COMP, SNX, CRV e MKR. À medida que a Capitalização de Mercado do SUSHI alcança o Top 5, o SUSHI será adicionado ao pool.

Etapa 2: emprestar todos os 6 tokens (UNI, AAVE, COMP, SNX, CRV e MKR) suportados pelo IndexPool através do SushiSwap.

Etapa 3: trocar UNI invocando a função swapExactAmountIn múltiplas vezes com os tokens emprestados (usando COMP como exemplo).

Aviso 1: aqui as múltiplas vezes são devido à restrição do MAX_IN_RATIO, podendo-se trocar no máximo metade do saldo do token de uma vez.

Aviso 2: nesta etapa, o poolValue será grandemente subestimado, pois o saldo de UNI (como o firstToken) no pool diminui muito.

Etapa 4: modificar o minimumBalance do SUSHI invocando a função updateMinimumBalance.

Note que o minimumBalance é menor que o valor normal devido ao poolValue anormal calculado na etapa 3.

Etapa 5: preparar tokens LP invocando a função joinswapExternAmountIn para fornecer liquidez. Veremos que esses tokens LP são usados para recomprar mais SUSHI.

Note que: a função joinswapExternAmountIn precisa ser invocada múltiplas vezes devido ao impacto do MAX_IN_RATIO.

Etapa 6: manipular o peso do SUSHI no pool DEFI5 primeiro emprestando uma enorme quantidade de SUSHI e transferindo-os para o pool, e então invocando a função gulp para definir o ready do SUSHI como true. Ao fazer isso, o peso inicial do SUSHI (denorm) se torna um valor elevado.

Etapa 7: trocar tokens LP de volta para tokens subjacentes (UNI, AAVE, COMP, SNX, CRV, MKR e SUSHI) invocando a função exitPool.

Note que a função exitPool NÃO considera o peso de cada token; como resultado, os tokens subjacentes serão devolvidos em proporções iguais.

Etapa 8: trocar tokens LP invocando a função joinswapExternAmountIn com SUSHI para fornecer liquidez. Mais tokens LP podem ser obtidos devido ao peso anormal do SUSHI naquele momento.

Note que a função joinswapPoolAmountIn irá cunhar o token LP com base no peso do token subjacente recebido (SUSHI neste caso).

Etapa 9: drenar o pool invocando a função exitPool com os tokens LP obtidos na etapa 8.

0x5. Análise do Lucro

Nossa investigação mostra que todo o dinheiro (incluindo as taxas de transação) utilizado pelo atacante provém do Tornado Cash.

No total, há duas transações de ataque:

  • Na primeira transação, o atacante obteve: 6.226,8 AAVE, 15 ETH, 192.358,6 UNI, 5.459,5 COMP, 721.611,3 CRV, 16.680,6 SNX, 406,5 MKR.

  • Na segunda transação, o atacante obteve: 109,6 MKR, 17.844 UMA, 1.002,4 COMP, 34.602,5 UNI, 131.645,4 BAT, 28.754,1 SNX, 1.273,6 AAVE, 124.194,2 CRV, 33.215,4 LINK, 5,24 YFI.

Além disso, o atacante também teve várias tentativas fracassadas.

No momento da redação deste artigo, o lucro obtido pelo atacante equivale a $16 milhões de dólares americanos e ainda não foi transferido.

Sobre a BlockSec

A BlockSec é uma empresa pioneira em segurança blockchain, fundada em 2021 por um grupo de especialistas em segurança de renome mundial. A empresa está comprometida em aprimorar a segurança e a usabilidade do emergente mundo Web3, visando facilitar sua adoção em massa. Para isso, a BlockSec oferece serviços de auditoria de segurança de contratos inteligentes e redes EVM, a plataforma Phalcon para desenvolvimento seguro e bloqueio proativo de ameaças, a plataforma MetaSleuth para rastreamento e investigação de fundos, e a extensão MetaSuites para construtores web3 navegarem com eficiência no mundo cripto.

Até o momento, a empresa atendeu mais de 300 clientes renomados, 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

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit