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
Análise do Incidente de Segurança do Indexed Finance