
SharkTeam : Analyse du principe de la vulnérabilité de falsification d'adresse arbitraire dans Multicall
TechFlow SélectionTechFlow Sélection

SharkTeam : Analyse du principe de la vulnérabilité de falsification d'adresse arbitraire dans Multicall
La cause profonde de cet incident d'attaque : dans ERC-2771, le [Forwarder] n'est pas conçu spécifiquement pour multicall.
Rédaction : SharkTeam
Le 8 décembre 2023, OpenZeppelin a publié une alerte de sécurité importante à destination de la communauté. L'alerte indique qu'une intégration du standard ERC-2771 combinée à des méthodes de type Multicall dans les projets pourrait présenter un risque d'attaque par usurpation d'adresse arbitraire.
SharkTeam a mené immédiatement une analyse technique de cet incident et résumé des mesures préventives afin que les projets futurs puissent en tirer des enseignements et contribuer ensemble à renforcer la sécurité dans l'industrie blockchain.
I. Analyse des transactions malveillantes
Étant donné qu'une série de transactions liées à cette vulnérabilité ont été observées, nous avons choisi d'analyser une transaction représentative.
Adresse de l’attaquant :
0xFDe0d1575Ed8E06FBf36256bcdfA1F359281455A
Transaction malveillante :
0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6
Processus de l'attaque :
1. Tout d'abord, l'attaquant (0xFDe0d157) a échangé 5 WETH contre environ 3 455 399 346 TIME.

2. Ensuite, l'attaquant (0xFDe0d157) a construit un paramètre « calldata » malveillant et appelé la fonction [Forwarder].execute.
3. Lors de l'appel à la fonction [Forwarder].execute, le « calldata » malveillant a déclenché la fonction multicall du contrat TIME. Puis, les données restantes dans le « calldata » ont déclenché l'exécution de la fonction burn du contrat TIME, provoquant ainsi la destruction des jetons TIME présents dans le pool.

II. Analyse de la vulnérabilité
Cet incident implique principalement trois composants : ERC2771, Multicall et un « calldata » soigneusement construit. Dans le contrat du jeton TIME, on peut observer les éléments suivants :

1. ERC2771 permet une simulation de msg.sender, autorisant un utilisateur à déléguer une transaction à un tiers [Forwarder], ce qui permet de réduire les frais de gaz. Lors de la soumission de la transaction, l'adresse msg.sender est ajoutée au « calldata ».
2. Le contrat du jeton TIME hérite de ERC2771Context. Lorsque le [Forwarder] appelle le contrat, _msgSender() vérifie les données du « calldata », effectue un décalage vers la droite et extrait les 20 derniers octets comme adresse attendue pour msg.sender.

3. Multicall est une méthode permettant de transformer un seul appel de fonction en une séquence d'appels multiples sur le même contrat. Elle prend en entrée un tableau d'appels encodés par l'utilisateur et les exécute via delegatecall(). Cela permet à l'utilisateur de combiner plusieurs opérations dans une seule transaction sans avoir besoin que celles-ci soient prédéfinies par le protocole, ce qui permet également de réduire les frais de gaz.

4. Concernant le « calldata » soigneusement construit, l'attaquant a invoqué la fonction [Forwarder].execute en y transmettant les paramètres appropriés.

Après formatage lisible de la valeur « data », on obtient :

L'attaquant (0xFDe0d157) a utilisé un décalage sur le « calldata » actuel pour obtenir une nouvelle valeur « data », puis a passé cette valeur à la fonction multicall(bytes[]). Les 4 premiers octets de la nouvelle donnée correspondent au sélecteur de la fonction burn(uint256), avec un paramètre amount fixé à 62227259510000000000000000000.
5. Dans la fonction multicall(bytes[]), un appel delegatecall() est fait vers la fonction burn(uint256). À la ligne 0x20, l'adresse 0x760dc1e043d99394a10605b2fa08f123d60faf84 correspond à celle ajoutée initialement à la fin du « calldata ». Cette adresse est le pool de liquidité TIME-ETH sur Uniswap v2, c’est-à-dire l’adresse attendue initialement comme msg.sender.

6. Pourquoi l'adresse msg.sender devient-elle celle du pool de liquidité TIME-ETH ? Initialement, msg.sender correspond à l'adresse du contrat [Forwarder]. Afin de vérifier si le [Forwarder] est digne de confiance, si c'est le cas, alors msg.sender est remplacé par les 20 derniers octets du « calldata ».
III. Recommandations de sécurité
La cause fondamentale de cet incident réside dans le fait que, dans ERC-2771, le [Forwarder] n'a pas été conçu spécifiquement pour être utilisé avec multicall. L'attaquant a inclus les paramètres associés à la fonction _msgSender() dans l'appel externe à multicall, notamment dans la fonction [Forwarder].execute utilisée ici. Au sein de la fonction multicall, certains appels intérieurs incluent eux aussi les paramètres de _msgSender(), ce qui permet à l'attaquant de tromper _msgSender(). Ainsi, en utilisant multicall pour appeler certaines fonctions, l'attaquant peut simuler un appel provenant d'une adresse arbitraire, et finalement détruire les jetons TIME présents dans le pool après avoir obtenu les droits nécessaires.
Face à ce type de menace, les mesures suivantes peuvent être mises en œuvre pour atténuer les risques :
1. Utiliser la nouvelle version corrigée d'OpenZeppelin. La nouvelle version de Multicall inclut désormais un suffixe « context » contenant la longueur des données ERC2771Context, permettant d'identifier la longueur attendue du contexte ERC-2771. Ainsi, tout appel provenant d’un [Forwarder] de confiance sera correctement reconnu et adapté pour chaque sous-appel de fonction.

Voici une comparaison entre la version vulnérable et la version corrigée :

2. Interdire à tout contrat d'appeler multicall afin d'empêcher son utilisation par un [Forwarder]. Par exemple, ThirdWeb a adopté cette approche. Comparé à la solution d'OpenZeppelin qui autorise toujours les appels multicall via un contrat, cette méthode est plus restrictive. Voici une comparaison entre la version vulnérable et la version corrigée de ThirdWeb :

[Clause de non-responsabilité] Le marché comporte des risques. Investissez avec prudence. Ce document ne constitue aucun conseil d'investissement. Les lecteurs doivent considérer si les opinions, points de vue ou conclusions exprimés dans cet article conviennent à leur situation particulière. Toute décision d'investissement prise sur cette base relève de leur entière responsabilité.
Bienvenue dans la communauté officielle TechFlow
Groupe Telegram :https://t.me/TechFlowDaily
Compte Twitter officiel :https://x.com/TechFlowPost
Compte Twitter anglais :https://x.com/BlockFlow_News










