0x.1 Antecedentes
A las 02:38 (UTC+8) del 15 de octubre de 2021, nuestro sistema de monitoreo interno detectó transacciones sospechosas de préstamos flash:

Tras la investigación, descubrimos que se trataba de un ataque de manipulación de precios dirigido a Indexed Finance. Específicamente, el atacante lanzó el ataque explotando la fórmula defectuosa (utilizada para calcular el precio) de este proyecto, y obtuvo una ganancia de 16 millones de dólares.
Ya existen algunas discusiones en las redes sociales, y el proyecto ha publicado un informe oficial post-mortem (Indexed Attack Post-Mortem). Sin embargo, los análisis existentes no ofrecen una comprensión completa de este incidente de seguridad. Por ello, en este blog, nos proponemos proporcionar un análisis exhaustivo que incluye el mecanismo del proyecto, la vulnerabilidad, el ataque y las ganancias.
0x1.1 Direcciones de Contratos Relevantes
-
MarketCapSqrtController: 0x120c6956d292b800a835cb935c9dd326bdb4e011
-
DEFI5: 0xfa6de2697d59e88ed7fc4dfe5a33dac43565ea41
-
CC10: 0x17ac188e09a7890a1844e5e65471fe8b0ccfadf3
0x1.2 Transacciones del Ataque
-
TX del Ataque I: 0x44aad3b853866468161735496a5d9cc961ce5aa872924c5d78673076b1cd95aa
-
TX del Ataque II: 0xbde4521c5ac08d0033019993b0e7e1d29b1457e80e7743d318a3c27649ca4417
0x2. Mecanismo de Indexed Finance
Para entender mejor la vulnerabilidad/ataque, usamos DEFI5 (es decir, el pool hackeado por el atacante) para demostrar el mecanismo de Indexed Finance.
0x2.1 Vinculación de Tokens
DEFI5 está diseñado para proporcionar el servicio de intercambio para los 5 principales tokens de proyectos DeFi de Ethereum. Específicamente, Indexed Finance actualizará el ranking de tokens según su capitalización de mercado a través de MarketCapSqrtController. Dado que el ranking de los 5 principales tokens puede cambiar con el tiempo, el número de tokens utilizados por el pool DEFI5 puede ser mayor que 5, como se muestra en el siguiente código:

La Figura 1 muestra que, para vincular un nuevo token, DEFI5 debe activar la función _bind invocada por la función reindexTokens, que solo puede ser invocada por la función reindexPools de MarketCapSqrtController:

La Figura 2 demuestra que MarketCapSqrtController primero obtiene información del token (incluyendo el TotalSupply y el precio) de los mercados, y luego calcula el ranking según su capacidad de mercado. Al invocar la función reindexPool, las direcciones de los tokens principales se pasarán como argumentos para invocar la función reindexTokens. Nótese que el nuevo token añadido será vinculado a DEFI5 sin reemplazar los tokens originales de DEFI5.
0x2.2 ¿Qué Sigue?
Después de la vinculación del token, DEFI5 debe establecer una variable llamada ready (que indica el estado del token) en true para habilitar el intercambio:

Según la lógica del código, aparte de la inicialización del contrato, ready solo puede establecerse en la función gulp.
Como se muestra en la Figura 3, esto ocurre cuando el saldo del token en DEFI5 es mayor o igual a _minimumBalances.
Mientras tanto, el peso inicial del token (es decir, denorm) se calculará en base a la siguiente fórmula:

0x3. Análisis de la Vulnerabilidad
El código vulnerable pertenece a la función updateMinimumBalance de MarketCapSqrtController.

Como se muestra en la Figura 4, updateMinimumBalance puede cambiar el minimumBalance de un token cuyo ready es false a 1/100 del poolValue. El cálculo del poolValue es la clave de la vulnerabilidad.

El cálculo de la Figura 5 simplemente implementa la siguiente fórmula:

Sin embargo, existen dos problemas potenciales en esta fórmula:
- usar la liquidez de un token para estimar el valor de todo el pool;
- los pesos del pool (
_totalWeight) y del token (token.denorm) no se ven afectados por el cambio de liquidez. De hecho, están influenciados por la Capacidad de Mercado de los mercados externos. Además, su cambio está limitado por el período de tiempo, es decir, aumenta o disminuye un 1% por hora.
En resumen, el atacante puede manipular poolValue usando el préstamo flash para provocar instantáneamente un gran cambio en la liquidez de un token, mientras que los pesos del pool y del token permanecen sin cambios.
Al hacer esto, el minimumBalance del token (cuyo ready es false) puede ser manipulado para lanzar el ataque de manipulación de precios.
0x4. Análisis del Ataque
El ataque consta de los siguientes 9 pasos:
Paso 1: invocando la función reindexPool para vincular SUSHI. Antes de la invocación, hay 6 tokens en el pool DEFI5, incluyendo UNI, AAVE, COMP, SNX, CRV y MKR. A medida que la Capacidad de Mercado de SUSHI se convierte en el Top 5, SUSHI se añadirá al pool.

Paso 2: tomando prestados los 6 tokens (UNI, AAVE, COMP, SNX, CRV y MKR) soportados por IndexPool a través de SushiSwap.

Paso 3: intercambiando UNI invocando la función swapExactAmountIn múltiples veces con los tokens prestados (tomando COMP como ejemplo).
Aviso 1: aquí las múltiples veces se deben a la restricción de
MAX_IN_RATIO, solo se puede intercambiar como máximo la mitad del saldo del token.Aviso 2: en este paso,
poolValueserá gravemente subestimado, porque el saldo de UNI (comofirstToken) en el pool disminuye considerablemente.

Paso 4: modificando el minimumBalance de SUSHI invocando la función updateMinimumBalance.
Nótese que
minimumBalancees menor que el valor normal debido alpoolValueanormal calculado en el paso 3.

Paso 5: preparando tokens LP invocando la función joinswapExternAmountIn para proveer liquidez. Veremos que estos tokens LP se usan para intercambiar de vuelta más SUSHI.
Nótese que: la función
joinswapExternAmountIndebe invocarse múltiples veces debido al impacto deMAX_IN_RATIO.

Paso 6: manipulando el peso de SUSHI en el pool DEFI5 primero tomando prestada una enorme cantidad de SUSHI y transfiriéndolos al pool, y luego invocando la función gulp para establecer ready de SUSHI en true. De esta forma, el peso inicial de SUSHI (denorm) se convierte en un valor alto.

Paso 7: intercambiando tokens LP de vuelta a tokens subyacentes (UNI, AAVE, COMP, SNX, CRV, MKR y SUSHI) invocando la función exitPool.
Nótese que la función
exitPoolNO considera el peso de cada token, por lo que los tokens subyacentes serán devueltos en proporciones iguales.
Paso 8: intercambiando tokens LP invocando la función joinswapExternAmountIn con SUSHI para proveer liquidez. Se pueden obtener más tokens LP debido al peso anormal de SUSHI en ese momento.


Nótese que la función joinswapPoolAmountIn acuñará el token LP basándose en el peso del token subyacente recibido (SUSHI en este caso).
Paso 9: vaciando el pool invocando la función exitPool con los tokens LP obtenidos en el paso 8.
0x5. Análisis de Ganancias
Nuestra investigación muestra que todo el dinero (incluidas las tarifas de transacción) utilizado por el atacante proviene de Tornado Cash.
En total, hay dos transacciones de ataque:
-
En la primera transacción, el atacante obtuvo: 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.
-
En la segunda transacción, el atacante cosechó: 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.
Además, el atacante también tuvo varios intentos fallidos.
Al momento de redactar este artículo, las ganancias obtenidas por el atacante ascienden a 16 millones de dólares estadounidenses y aún no han sido transferidas.
Acerca de BlockSec
BlockSec es una empresa pionera en seguridad blockchain establecida en 2021 por un grupo de expertos en seguridad de renombre mundial. La empresa está comprometida con mejorar la seguridad y la usabilidad para el emergente mundo Web3 con el fin de facilitar su adopción masiva. Con este fin, BlockSec proporciona servicios de auditoría de seguridad de contratos inteligentes y cadenas EVM, la plataforma Phalcon para el desarrollo de seguridad y el bloqueo proactivo de amenazas, la plataforma MetaSleuth para el seguimiento e investigación de fondos, y la extensión MetaSuites para que los desarrolladores de web3 naveguen eficientemente en el mundo cripto.
Hasta la fecha, la empresa ha prestado servicios a más de 300 clientes de renombre como MetaMask, Uniswap Foundation, Compound, Forta y PancakeSwap, y ha recibido decenas de millones de dólares en dos rondas de financiamiento de inversores destacados, entre ellos Matrix Partners, Vitalbridge Capital y Fenbushi Capital.
Sitio web oficial: https://blocksec.com/
Cuenta oficial de Twitter: https://twitter.com/BlockSecTeam



