Web3 sécurité avertissement | Pertes jusqu'à 20 millions de dollars, analyse de l'incident d'attaque Sonne Finance

Le 15 mai 2024, Sonne Finance a subi une attaque sur Optimism on-chain, avec des pertes allant jusqu’à 2 k 0000 $.

Après l'attaque, l'utilisateur @tonyke_bot sur X a tweeté qu'il a protégé environ 100 dollars en jetons de Sonne Finance dans le pool de mise en gage (également appelé le marché, similaire au cToken dans Compound) pour un montant d'environ 6,5 millions de dollars.

\_bot/status/1790547461611860182

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

Après avoir découvert l’attaque, l’équipe de projet de Sonne Finance a rapidement suspendu tous les marchés d’Optimism et a déclaré que les marchés de Base étaient sûrs.

(**)

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

Briefing d’attaque

Sonne Finance est un protocole de prêt et d'emprunt décentralisé basé sur Compound V2, fourni sur Optimism, offrant des services financiers aux particuliers, aux institutions et aux protocoles. Le protocole Sonne Finance agrège les actifs de jetons des utilisateurs pour former un pool de liquidité de prêt, offrant aux utilisateurs des services de prêt similaires à ceux d'une banque. Comme Compound, les participants au protocole peuvent mettre en gage leurs jetons dans le pool de liquidité de prêt de Sonne Finance et recevoir des certificats soToken (similaires aux cToken). Les soTokens sont des certificats d'actifs générateurs de revenus, qui génèrent des rendements à mesure que les blocs avancent, tout en recevant également des incitations en tokens SONNE. Les détenteurs de soTokens peuvent également emprunter d'autres jetons à partir de la pool d'actifs de prêt de Sonne, par exemple, ils peuvent mettre en gage une certaine quantité de USDC pour obtenir des certificats soUSDC, puis emprunter du WETH pour une circulation ultérieure. Les prêts et emprunts avec gages multiples sont possibles dans le protocole Sonne Finance. Au cours du processus de prêt et d'emprunt avec gages, le protocole calcule automatiquement la santé (Health Factor) de l'adresse du participant. Lorsque la santé est inférieure à 1, les actifs de gage de cette adresse peuvent être liquidés, et le liquidateur peut également recevoir une récompense de liquidation.

La relation entre le jeton sous-jacent déposé par l’utilisateur et le nombre de soTokens minting est principalement liée à une variable appelée exchangeRate, qui peut être grossièrement utilisée pour représenter la valeur de chaque jeton sous-jacent soToken le plus long ou le moins sous-jacent. Le taux de change est calculé comme suit :

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

Dans la formule ci-dessus, totalCash fait référence au nombre de tokens sous-jacents détenus par soToken, totalBorrows fait référence au montant de tokens sous-jacents prêtés sur un marché, totalReserves fait référence au montant total des réserves (y compris les intérêts payés par les emprunteurs) et totalSupply fait référence au nombre de soTokens de minting.

Lors de l’échange, l’utilisateur peut spécifier la quantité de tokens sous-jacents à racheter, redeemAmount, pour calculer le nombre de soTokens qui doivent être brûlés, redeemTokens, la méthode de calcul est à peu près « redeemTokens = redeemAmount / exchangeRat », notez qu’il n’y a pas de traitement de la perte de précision ici.

La nature de cette attaque est que lorsque le marché (soToken) a été créé, l'attaquant a effectué une opération de minting avec une petite quantité de jetons sous-jacents pour créer peu de soToken, ce qui a entraîné une valeur "totalSupply" trop faible pour les soToken. Ensuite, l'attaquant a exploité la vulnérabilité de perte de précision des contrats Solidity en envoyant directement des jetons sous-jacents au contrat soToken (sans minting de nouveaux soToken, ce qui signifie que "totalSupply" reste inchangé mais "totalCash" augmente). Cette opération a augmenté la variable "totalCash" du contrat, mais "totalSupply" est resté inchangé, ce qui a entraîné une augmentation du taux de change. Finalement, lors de la récupération des jetons sous-jacents, l'attaquant n'a eu besoin de détruire qu'une quantité inférieure de soToken par rapport à celle qu'il avait mintée lors de l'opération de minting. L'attaquant a utilisé les soToken obtenus pour emprunter des jetons sous-jacents tels que WETH et USDC à partir d'autres soToken (comme soWETH, soUSDC), réalisant ainsi un profit pouvant atteindre 20 millions de dollars.

**Adresse critique impliquée dans l’attaque

Trading prêt à l’attaque :

> > ** > \u003e

Attaquer les transactions rentables :

>\u003e > \u003e ** \u003e \u003e

Adresse liée à l’EOA d’attaque :

\u003e

0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb \u003e \u003e

\u003e \u003e

0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43 \u003e

Attaqueur (contrat) adresse associée :

\u003e

0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8

\u003e

0x02fa2625825917e9b1f8346a465de1bbc150c5b9

"\u003e "

jeton sous-jacent (VELO Jeton V2) :

\u003e

0x9560e827af36c94d2ac33a39bce1fe78631088db > >

漏洞合约(soVELO,类似于 Compound 的 cToken):

\u003e \u003e 0xe3b81318b1b6776f0877c3770afddff97b9f5fe5 \u003e

X 上 @tonyke_bot 用户救援交易:

> > **

\u003e

Analyse du processus d'attaque

Résumé du contexte précédent

Sonne Finance a récemment approuvé une proposition visant à ajouter le marché VELO à Sonne Finance (), et a organisé cinq transactions à exécuter dans deux jours via un portefeuille à signatures multiples (). Ces cinq transactions sont utilisées pour créer le marché VELO (contrat soVELO) et configurer certains paramètres clés de ce marché, tels que le modèle de taux d'intérêt, l'oracle de prix et le facteur de garantie. Une fois le marché VELO créé, les utilisateurs peuvent déposer des jetons VELO pour créer des jetons soVELO, qui peuvent ensuite être utilisés pour emprunter d'autres soTokens.

Préparation de l’attaque

La phase de préparation de l'attaque consiste principalement en ce que l'attaquant, après la fin de la période de verrouillage de deux jours de la proposition, crée un marché VELO (contrat soVELO) en fonction des informations contenues dans la proposition du projet Sonne Finance, configure les paramètres clés et utilise des jetons VELO en garantie pour frapper des jetons soVELO dans le contrat soVELO. En même temps, l'attaquant envoie directement ses jetons VELO détenus au contrat soVELO pour augmenter le taux de change, en préparation pour les bénéfices futurs de l'attaque.

具体步骤如下:

  1. Après la fin de la période de verrouillage de deux jours, l'attaquant a d'abord regroupé les opérations des quatre premières transactions prévues dans la proposition en une seule transaction (transaction 0x45c0cc), afin de créer un marché VELO (contrat soVELO) et de configurer les paramètres clés. Lors de l'initialisation du marché VELO, le taux de change est fixé à "200 000 000 000 000 000 000 000 000".
  2. L'attaquant appelle la fonction "mint" du contrat soVELO pour déposer des jetons VELO et les frapper en jetons soVELO. L'attaquant spécifie "mintAmount" comme étant "400,000,001" (la quantité de jetons VELO). À partir de la fonction "exchangeRateStoredInternal", on peut voir que le taux de change est celui défini à l'étape 1 car le "totalSuppl" des jetons soVELO est de 0. Selon la formule "mintTokens = actualMintAmount / exchangeRate", cela donne un nombre de 2 jetons soVELO à frapper. En résumé, à cette étape, l'attaquant dépose 400,000,001 jetons VELO dans le contrat soVELO et obtient 2 jetons soVELO.

soVELO.mint:

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析 3. L'attaquant a envoyé directement des jetons VELO à soVELO en envoyant des jetons VELO avec une valeur de "2,552,964,259,704,265,837,526" à soVELO. À ce stade, le contrat soVELO détient plus de jetons VELO, mais comme il n'y a pas de nouvelle émission de jetons soVELO, le totalSupply reste inchangé, ce qui signifie que le taux de change calculé selon la formule exchangeRate augmentera. 4. L'attaquant a transféré à plusieurs reprises les jetons soVELO qu'il détenait, les transférant finalement à un autre EOA d'attaque 0xae4a.

Attaque pour en tirer profit

Le stade de profit de l'attaque est principalement lorsque l'attaquant exécute la cinquième transaction de proposition et envoie directement le jeton VELO emprunté à partir du contrat soVELO via un prêt flash pour augmenter davantage le taux de change. Ensuite, l'attaquant utilise les jetons soVELO d'une valeur de 2 dans sa possession pour emprunter des jetons sous-jacents tels que WETH, USDC, etc. dans d'autres contrats soToken. Ces parties deviennent les bénéfices de l'attaquant. Ensuite, l'attaquant rachète ses propres jetons sous-jacents dans le contrat soVELO. En raison de l'augmentation du taux de change et des pertes de précision lors du calcul des jetons soVELO à détruire pour le rachat, l'attaquant peut finalement racheter presque tous les jetons VELO précédemment déposés en utilisant uniquement des jetons soVELO d'une valeur de 1. On peut comprendre que l'attaquant utilise les jetons soVELO d'une valeur de 1 pour emprunter WETH, USDC, etc. des autres soToken et réaliser des bénéfices. L'attaquant répète cette méthode d'attaque plusieurs fois pour réaliser d'énormes profits.

Les étapes spécifiques sont les suivantes :

  1. L'attaquant effectue la cinquième transaction de l'affaire et définit le facteur d'emprunt spécifié dans la proposition.
  2. L'attaquant emprunte instantanément des jetons VELO d'une valeur de "35 469 150 965 253 049 864 450 449" du pool VolatileV2 AMM - USDC/VELO, ce qui déclenche la fonction hook de l'attaquant. Dans la fonction hook, l'attaquant continue d'exécuter l'attaque.
  3. L'attaquant envoie les jetons VELO qu'il détient au contrat soVELO pour augmenter davantage le taux de change. Actuellement, le contrat soVELO compte un total de jetons VELO d'une valeur de "35,471,703,929,512,754,530,287,976" (les jetons VELO transférés trois fois par l'attaquant inclus).
  4. L'attaquant crée un nouveau contrat 0xa16388a6210545b27f669d5189648c1722300b8b, et dans le constructeur, transfère 2 jetons soVELO détenus au nouveau contrat créé 0xa163 (ci-après dénommé attaquant 0xa163).
  5. L’attaquant prête 0xa163 un WETH d’une valeur de « 265 842 857 910 985 546 929 » à partir du Jeton soWETH qu’il détient.
  6. L'attaquant 0xa163 appelle la fonction "redeemUnderlying" de soVELO en spécifiant la valeur de rachat des jetons VELO à "35,471,603,929,512,754,530,287,976" (pratiquement la quantité de jetons VELO que l'attaquant a précédemment transférée ou hypothéquée dans le contrat soVELO). À ce stade, il est nécessaire de calculer la quantité de jetons soVELO à détruire pour le rachat en utilisant la formule "redeemTokens = redeemAmountIn / exchangeRate".

Depuis la fonction "exchangeRateStoredInternal", on peut voir que puisque le "totalSupply" est de 2 et non de 0 à ce stade, il est nécessaire de calculer la valeur de "exchangeRate" en utilisant la formule "exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply". Actuellement, le "exchangeRate" est de "17 735 851 964 756 377 265 143 988 000 000 000 000 000 000", cette valeur est bien supérieure au taux de change initial fixé à "200 000 000 000 000 000 000 000 00".

根据新的 exchangeRate 计算出的「 redeemTokens 」的值为「 1.99 」,由于 Solidity 向下取整的特性,「 redeemTokens 」的值最终为 1。也就意味着攻击者 0xa163 使用数值为 1 的 soVELO 代币,赎回了此前存入的几乎所有的 VELO 代币。同时攻击者 0xa163 也赚取了从 soWETH 中借出的数值为「 265,842,857,910,985,546,929 」的 WETH。

soVELO.redeemSous-jacent :Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

soVELO.exchangeRateStoredInternal :Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析 7. L’attaquant transfère 0xa163 tous les WETH empruntés et rachetés VELO Jeton à l’attaquant supérieur, puis s’autodétruit. 8. L'attaquant appelle la fonction "liquidateBorrow" de soWETH pour liquider une partie des actifs empruntés par le contrat 0xa163 nouvellement créé, dans le but de récupérer le jeton soVELO verrouillé avec une valeur de 1. Actuellement, l'attaquant ne détient qu'un jeton soVELO d'une valeur de 1. 9. L'attaquant appelle la fonction "mint" de soVELO pour hypothéquer à nouveau des jetons soVELO dans le but d'atteindre une valeur de 2 jetons soVELO, puis exécute à nouveau les étapes 3 à 8 ci-dessus pour obtenir des bénéfices supplémentaires en sous-jacents. 10. L’attaquant effectue plusieurs fois l’étape 9, rembourse les prêts flash et quitte le marché avec un bénéfice.

Comment faire levier sur 6,5 millions de dollars avec 100 dollars

Après l'attaque, l'utilisateur @tonyke_bot sur X a utilisé 1144 jetons VELO pour les mettre en gage dans le contrat soVELO lors de la transaction 0x0a284cd, ce qui a permis de créer 0.00000011 jetons soVELO. Cette opération a empêché l'attaquant de continuer l'attaque, car elle a modifié la taille de totalSupply dans soVELO ainsi que la quantité de jetons VELO détenus totalCash. Comme la croissance de totalSupply a un impact plus important sur le calcul du taux de change que la croissance de totalCash, le taux de change diminue, ce qui empêche l'attaquant de profiter de la perte de précision pour gagner des soVELO. Cela rend l'attaque impossible à poursuivre.

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

Suivi des fonds

Les attaquants ont transféré les fonds peu de temps après s’être emparés des produits illégaux, dont la plupart ont été transférés aux 4 adresses suivantes, certaines pour poursuivre l’attaque à une autre adresse, et d’autres pour le blanchiment d’argent :

  1. 0x4ab93fc50b82d4dc457db85888dfdae28d29b98d

L’attaquant a transféré 198 WETH à l’adresse, puis l’adresse a utilisé les mêmes tactiques d’attaque pour obtenir des produits illégaux dans les transactions suivantes :

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

Après l’attaque, le Adresse a transféré le produit de la vente à 0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb.

  1. 0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb

L'attaquant a transféré 724277 USDC et 2353 VELO à cette adresse et a échangé les USDC contre de l'Ether. Ensuite, une partie des fonds a été immédiatement transférée vers le pont cross-chain Stargate, tandis que la majeure partie des fonds illégaux est restée dans cette adresse.

Web3安全警示丨损失高达2000万美元,Sonne Finance攻击事件分析

  1. 0xbd18100a168321701955e348f03d0df4f517c13b

L’attaquant a transféré 33 WETH à l’adresse et a utilisé la chaîne peel pour essayer le blanchiment d’argent, le lien de blanchiment d’argent est le suivant :

0xbd18100a168321701955e348f03d0df4f517c13b -> 0x7e97b74252b6df53caf386fb4c54d4fb59cb6928 -> 0xc521bde5e53f537ff208970152b75a003093c2b4 -> * 0x9f09ec563222fe52712dc413d0b7b66cb5c7c795*。

  1. 0x4fac0651bcc837bf889f6a7d79c1908419fe1770

L'attaquant a transféré 563 WETH à cette adresse, puis a transféré ces fonds à 0x1915F77A116dcE7E9b8F4C4E43CDF81e2aCf9C68, sans autre action pour le moment.

L'approche utilisée par les attaquants pour le blanchiment d'argent cette fois-ci est relativement professionnelle, avec une diversité de méthodes. Par conséquent, en tant que participants à Web3, il est important que nous continuions à renforcer notre capacité de lutte contre le blanchiment d'argent en améliorant la sécurité de nos projets DeFi grâce à des produits de sécurité des transactions blockchain tels que KYT et AML.

Conseils de sécurité

  1. La perte de précision doit être prise en compte. Les problèmes de sécurité causés par la perte de précision apparaissent les uns après les autres, en particulier dans les projets Defi, où la perte de précision entraîne souvent de graves pertes financières. Il est recommandé que l’équipe de projet et les auditeurs de sécurité examinent attentivement le code présentant une perte de précision dans le projet et fassent un bon travail de test pour éviter autant que possible la vulnérabilité.
  2. Il est recommandé que la création et les premières opérations de minting de staking d’un marché similaire à cToken dans Compound soient effectuées par des utilisateurs privilégiés pour éviter d’être manipulés par des attaquants, afin de manipuler le taux de change.
  3. Lorsque des variables clés dans le contrat dépendent des valeurs de "this.balance" ou "token.balanceOf()", il est important de prendre en compte les conditions dans lesquelles ces variables clés peuvent être modifiées. Par exemple, est-il possible de modifier directement la valeur de cette variable en envoyant des jetons ou des jetons natifs au contrat, ou est-ce que seule l'appel d'une fonction spécifique permet de modifier cette variable.

Ce texte a été rédigé par Cara (compte X @Cara6289) et XiG (compte X @SHXiGi) de l'équipe ZAN.

Voir l'original
  • Récompense
  • Commentaire
  • Partager
Commentaire
Aucun commentaire