Récemment, en travaillant avec l'un de nos clients, nous avons découvert un bug intéressant qui a le potentiel d'être un vecteur d'attaque pour certains projets DeFi. Cette erreur est particulièrement liée à la norme de jeton bien connue ERC777. De plus, il ne s'agit pas simplement d'un simple problème de réentrée courant chez les pirates informatiques bien connus.
Cet article fournit une explication complète de ERC777, couvrant tous les détails nécessaires. Il existe peu de ressources pour approfondir les spécificités des jetons ERC777, et cet article est un guide détaillé précieux pour quiconque souhaite en savoir plus sur les jetons ERC777.
Dans la dernière partie de l'article, nos découvertes récentes seront expliquées.
Une brève description du vecteur d'attaque
Cette vulnérabilité tire parti des caractéristiques d'ERC777 et peut définir une fonction de réception Hook. En utilisant la possibilité d'effectuer des appels arbitraires dans le contrat cible, un appelant malveillant peut appeler le contrat de registre ERC777 et attribuer une adresse Hook spécifique au contrat cible. Par conséquent, chaque fois que le contrat cible recevra des jetons ERC777 à l'avenir, le contrat Hook de l'attaquant sera déclenché. Ce crochet peut être exploité de différentes manières : soit pour des attaques de réentrance visant à voler des jetons, soit simplement pour annuler des transactions, empêchant le contrat cible d'envoyer ou de recevoir des jetons ERC777.
ERC777 et son crochet
Qu'est-ce que l'ERC777
ERC777 est l'une des normes de jeton avec crochet de transfert. Voici la description de l'EIP : , et voici une pratique ERC777 [4] 。
La principale motivation pour la mise en œuvre des jetons ERC777 est d'imiter le comportement des transferts de jetons natifs. En déclenchant des contrats intelligents lorsque des jetons sont reçus, les développeurs peuvent exécuter une logique spécifique pour améliorer les fonctionnalités et créer des interactions de jetons plus dynamiques.
Cependant, ces appels supplémentaires pendant le processus de transfert rendent ERC777 différent des jetons ERC20. Ces crochets introduisent un nouveau vecteur d'attaque qui pourrait affecter les contrats intelligents qui n'ont pas été conçus pour gérer des appels supplémentaires lors des transferts de jetons. Un tel comportement inattendu crée des risques de sécurité pour ces contrats.
Voici une liste de certains jetons ERC777 avec une certaine liquidité sur le réseau principal Ethereum :
Lorsque le crochet se produit
Les jetons ERC20 mettent simplement à jour les soldes lors des transferts. Mais les jetons ERC777 font ceci :
Effectuez un appel Hook à l'adresse de l'initiateur du jeton
Mettre à jour le solde
Effectuez un appel de crochet à l'adresse du récepteur du jeton
Ceci est bien illustré dans le jeton VRA :
code source:
Examinons maintenant le code de ces appels :
comme tu as vu :
Cette fonction lit un contrat appelé implémenteur à partir de _ERC1820_REGISTRY
Si la fonction trouve un implémenteur, cet implémenteur est appelé.
Explorons ce registre et voyons ce que sont les implémenteurs.
Registre et implémenteurs
Tous les jetons ERC777 sont liés au contrat du registre :
Cette adresse est utilisée par les jetons ERC777 pour stocker les destinataires Hook définis. Ces récepteurs Hook sont appelés "implémenteurs d'interface".
Cela signifie qu'Alice peut choisir Bob comme implémenteur d'interface. Si Alice reçoit ou envoie des jetons ERC777, Bob recevra le Hook.
Alice peut gérer différents types de Hook. Par conséquent, lorsqu'Alice envoie des jetons, elle peut choisir Bob comme implémenteur de l'interface, et uniquement lorsqu'Alice reçoit des jetons, elle choisit Tom comme implémenteur.
Elle peut également choisir différents implémenteurs d'interface pour différents jetons dans la plupart des cas.
Ces préférences sont stockées dans ce registre mappé :
_interfaceHash est l'ID de l'implémenteur d'interface choisi par Alice pour un événement.
Et n'importe qui peut lire l'implémenteur d'interface d'Alice avec cette fonction :
Comme vous pouvez le voir, c'est la fonction que nous avons rencontrée plus tôt dans le code VRA.
La variable _TOKENS_SENDER_INTERFACE_HASH est utilisée comme _interfaceHash, qui peut être n'importe quel octet. Mais le jeton VRA utilise ces octets pour identifier ce type de Hook :
Crochet de réception
Pour configurer une fonction de réception Hook, Alice n'a qu'à appeler cette fonction sur le registre et entrer l'adresse de Bob comme paramètre _implementer.
Elle doit également spécifier un _interfaceHash. Elle obtiendra ce _TOKENS_SENDER_INTERFACE_HASH à partir du code du jeton VRA.
Il y a un autre détail important.
Après avoir configuré l'implémenteur pour le VRA ci-dessus, Alice saura également que même si d'autres jetons ERC777 sont transférés, Bob recevra l'appel. Comme imBTC [5] , imBTC a le même _interfaceHash sur les jetons envoyés.
Cela est dû au fait que tous les jetons ERC777 partagent le même contrat de registre pour stocker les préférences Hook. Mais c'est aux jetons ERC777 d'attribuer des noms à leurs crochets, et bien qu'ils soient parfois similaires, pas toujours.
Comment trouver des jetons ERC777
L'appel du registre est une fonctionnalité de tous les ERC777. Nous pouvons donc essayer dune.com [6] pour appeler tous les contrats intelligents qui appellent le registre.
Nous pouvons utiliser ce script SQL. En fait, nous aurions dû filtrer en plus les adresses de jeton, mais au moins nous avons eu un départ parfait et nous nous sommes retrouvés avec 78 adresses.
NDLR : tableau des traces de dunes [7] Enregistrera l'enregistrement d'appel interne de la transaction.
Ce registre est-il la seule possibilité ?
Théoriquement, personne ne peut garantir qu'un jeton utilise ce contrat 0x1820 comme registre. Mais nous pouvons utiliser dune.com [8] Venez vérifier.
Nous avons vérifié et 0x1820 est le seul registre avec de précieux jetons ERC777. Les jetons des autres registres n'ont pas la même valeur.
La situation générale des jetons Hookable
ERC777 n'est pas seulement une norme avec des crochets. Également ERC223, ERC995 ou ERC667. Ils ne sont pas si inhabituels. Vous devez avoir entendu parler du jeton LINK qui implémente ERC667 [9] 。
Vecteur d'attaque utilisant un appel arbitraire
Il s'agit d'un vecteur d'attaque récemment découvert pour l'un de nos clients.
Les chercheurs supposent généralement que les jetons ERC777 effectuent des appels aux appelants et aux récepteurs. Mais en fait, l'initiateur et le récepteur peuvent choisir n'importe quel "Bob" comme récepteur Hook.
Alors imaginez ce qui se passe lorsqu'il est combiné avec ces contrats qui font des appels arbitraires à n'importe quelle adresse avec n'importe quelles données ?
Il existe des fonctions d'appel arbitraires qui peuvent être largement utilisées dans les agrégateurs DEX, les portefeuilles et les contrats multi-appels.
Note du traducteur : La fonction d'appel arbitraire signifie qu'il existe une fonction comme celle-ci dans le contrat :
fonction ute(adresse cible, valeur uint, signature mémoire chaîne, données mémoire octets, uint eta) public payable ;
Il peut appeler n'importe quelle autre méthode.
Méthode d'attaque :
L'attaquant trouve un contrat cible (Target) qui autorise des appels de fonction arbitraires
L'attaquant appelle la cible :
3.registy1820.setInterfaceImplementer(Cible, hookHash, Attaquant)
Maintenant, notre attaquant est l'implémenteur de la cible
L'attaquant sera appelé avec le hookHash utilisé dans le jeton ERC777.
Chaque fois que le contrat cible (Target) reçoit des jetons ERC777, l'attaquant recevra un appel Hook.
Les attaques suivantes varient en fonction du code cible :
L'attaquant peut revenir lorsque certains utilisateurs exécutent des fonctions dans le contrat cible
L'attaquant peut revenir en arrière directement, de sorte que la transaction de l'utilisateur soit restaurée directement
Si l'agrégateur DEX calcule que le meilleur chemin de conversion passe par une paire de trading DEX avec des jetons ERC777, il peut rencontrer des problèmes.
Protéger
Après des heures de discussions avec les clients, nous avons trouvé une solution qui ne casse pas les appels arbitraires.
Il est préférable que le côté projet limite l'utilisation de Registry1820 comme adresse de tout appel. Par conséquent, aucun attaquant ne peut exploiter des appels arbitraires pour définir l'implémenteur d'interface.
Parler d'expérience
Les projets et les auditeurs doivent prêter attention au comportement Hook décrit dans ERC777. Ces jetons effectuent des appels non seulement vers les récepteurs et les initiateurs, mais également vers d'autres récepteurs Hook.
En ce sens, les projets qui autorisent des appels arbitraires doivent faire particulièrement attention et envisager un autre vecteur d'attaque pour ERC777.
Voir l'original
Cette page peut inclure du contenu de tiers fourni à des fins d'information uniquement. Gate ne garantit ni l'exactitude ni la validité de ces contenus, n’endosse pas les opinions exprimées, et ne fournit aucun conseil financier ou professionnel à travers ces informations. Voir la section Avertissement pour plus de détails.
Problèmes de sécurité possibles avec ERC777 et contrats d'appel arbitraires
Récemment, en travaillant avec l'un de nos clients, nous avons découvert un bug intéressant qui a le potentiel d'être un vecteur d'attaque pour certains projets DeFi. Cette erreur est particulièrement liée à la norme de jeton bien connue ERC777. De plus, il ne s'agit pas simplement d'un simple problème de réentrée courant chez les pirates informatiques bien connus.
Cet article fournit une explication complète de ERC777, couvrant tous les détails nécessaires. Il existe peu de ressources pour approfondir les spécificités des jetons ERC777, et cet article est un guide détaillé précieux pour quiconque souhaite en savoir plus sur les jetons ERC777.
Dans la dernière partie de l'article, nos découvertes récentes seront expliquées.
Une brève description du vecteur d'attaque
Cette vulnérabilité tire parti des caractéristiques d'ERC777 et peut définir une fonction de réception Hook. En utilisant la possibilité d'effectuer des appels arbitraires dans le contrat cible, un appelant malveillant peut appeler le contrat de registre ERC777 et attribuer une adresse Hook spécifique au contrat cible. Par conséquent, chaque fois que le contrat cible recevra des jetons ERC777 à l'avenir, le contrat Hook de l'attaquant sera déclenché. Ce crochet peut être exploité de différentes manières : soit pour des attaques de réentrance visant à voler des jetons, soit simplement pour annuler des transactions, empêchant le contrat cible d'envoyer ou de recevoir des jetons ERC777.
ERC777 et son crochet
Qu'est-ce que l'ERC777
ERC777 est l'une des normes de jeton avec crochet de transfert. Voici la description de l'EIP : , et voici une pratique ERC777 [4] 。
La principale motivation pour la mise en œuvre des jetons ERC777 est d'imiter le comportement des transferts de jetons natifs. En déclenchant des contrats intelligents lorsque des jetons sont reçus, les développeurs peuvent exécuter une logique spécifique pour améliorer les fonctionnalités et créer des interactions de jetons plus dynamiques.
Cependant, ces appels supplémentaires pendant le processus de transfert rendent ERC777 différent des jetons ERC20. Ces crochets introduisent un nouveau vecteur d'attaque qui pourrait affecter les contrats intelligents qui n'ont pas été conçus pour gérer des appels supplémentaires lors des transferts de jetons. Un tel comportement inattendu crée des risques de sécurité pour ces contrats.
Voici une liste de certains jetons ERC777 avec une certaine liquidité sur le réseau principal Ethereum :
Lorsque le crochet se produit
Les jetons ERC20 mettent simplement à jour les soldes lors des transferts. Mais les jetons ERC777 font ceci :
Effectuez un appel Hook à l'adresse de l'initiateur du jeton
Mettre à jour le solde
Effectuez un appel de crochet à l'adresse du récepteur du jeton
Ceci est bien illustré dans le jeton VRA :
code source:
Examinons maintenant le code de ces appels :
comme tu as vu :
Explorons ce registre et voyons ce que sont les implémenteurs.
Registre et implémenteurs
Tous les jetons ERC777 sont liés au contrat du registre :
Cette adresse est utilisée par les jetons ERC777 pour stocker les destinataires Hook définis. Ces récepteurs Hook sont appelés "implémenteurs d'interface".
Cela signifie qu'Alice peut choisir Bob comme implémenteur d'interface. Si Alice reçoit ou envoie des jetons ERC777, Bob recevra le Hook.
Alice peut gérer différents types de Hook. Par conséquent, lorsqu'Alice envoie des jetons, elle peut choisir Bob comme implémenteur de l'interface, et uniquement lorsqu'Alice reçoit des jetons, elle choisit Tom comme implémenteur.
Elle peut également choisir différents implémenteurs d'interface pour différents jetons dans la plupart des cas.
Ces préférences sont stockées dans ce registre mappé :
_interfaceHash est l'ID de l'implémenteur d'interface choisi par Alice pour un événement.
Et n'importe qui peut lire l'implémenteur d'interface d'Alice avec cette fonction :
Comme vous pouvez le voir, c'est la fonction que nous avons rencontrée plus tôt dans le code VRA.
La variable _TOKENS_SENDER_INTERFACE_HASH est utilisée comme _interfaceHash, qui peut être n'importe quel octet. Mais le jeton VRA utilise ces octets pour identifier ce type de Hook :
Crochet de réception
Pour configurer une fonction de réception Hook, Alice n'a qu'à appeler cette fonction sur le registre et entrer l'adresse de Bob comme paramètre _implementer.
Elle doit également spécifier un _interfaceHash. Elle obtiendra ce _TOKENS_SENDER_INTERFACE_HASH à partir du code du jeton VRA.
Il y a un autre détail important.
Après avoir configuré l'implémenteur pour le VRA ci-dessus, Alice saura également que même si d'autres jetons ERC777 sont transférés, Bob recevra l'appel. Comme imBTC [5] , imBTC a le même _interfaceHash sur les jetons envoyés.
Cela est dû au fait que tous les jetons ERC777 partagent le même contrat de registre pour stocker les préférences Hook. Mais c'est aux jetons ERC777 d'attribuer des noms à leurs crochets, et bien qu'ils soient parfois similaires, pas toujours.
Comment trouver des jetons ERC777
L'appel du registre est une fonctionnalité de tous les ERC777. Nous pouvons donc essayer dune.com [6] pour appeler tous les contrats intelligents qui appellent le registre.
Nous pouvons utiliser ce script SQL. En fait, nous aurions dû filtrer en plus les adresses de jeton, mais au moins nous avons eu un départ parfait et nous nous sommes retrouvés avec 78 adresses.
Ce registre est-il la seule possibilité ?
Théoriquement, personne ne peut garantir qu'un jeton utilise ce contrat 0x1820 comme registre. Mais nous pouvons utiliser dune.com [8] Venez vérifier.
il renvoie ces adresses
0x1820a4b7618bde71dce8cdc73aab6c95905fad24 0xc0ce3461c92d95b4e1d3abeb5c9d378b1e418030 0x820c4597fc3e4193282576750ea4fcfe34ddf0a7
Nous avons vérifié et 0x1820 est le seul registre avec de précieux jetons ERC777. Les jetons des autres registres n'ont pas la même valeur.
La situation générale des jetons Hookable
ERC777 n'est pas seulement une norme avec des crochets. Également ERC223, ERC995 ou ERC667. Ils ne sont pas si inhabituels. Vous devez avoir entendu parler du jeton LINK qui implémente ERC667 [9] 。
Vecteur d'attaque utilisant un appel arbitraire
Il s'agit d'un vecteur d'attaque récemment découvert pour l'un de nos clients.
Les chercheurs supposent généralement que les jetons ERC777 effectuent des appels aux appelants et aux récepteurs. Mais en fait, l'initiateur et le récepteur peuvent choisir n'importe quel "Bob" comme récepteur Hook.
Alors imaginez ce qui se passe lorsqu'il est combiné avec ces contrats qui font des appels arbitraires à n'importe quelle adresse avec n'importe quelles données ?
Il existe des fonctions d'appel arbitraires qui peuvent être largement utilisées dans les agrégateurs DEX, les portefeuilles et les contrats multi-appels.
Méthode d'attaque :
Si l'agrégateur DEX calcule que le meilleur chemin de conversion passe par une paire de trading DEX avec des jetons ERC777, il peut rencontrer des problèmes.
Protéger
Après des heures de discussions avec les clients, nous avons trouvé une solution qui ne casse pas les appels arbitraires.
Il est préférable que le côté projet limite l'utilisation de Registry1820 comme adresse de tout appel. Par conséquent, aucun attaquant ne peut exploiter des appels arbitraires pour définir l'implémenteur d'interface.
Parler d'expérience
Les projets et les auditeurs doivent prêter attention au comportement Hook décrit dans ERC777. Ces jetons effectuent des appels non seulement vers les récepteurs et les initiateurs, mais également vers d'autres récepteurs Hook.
En ce sens, les projets qui autorisent des appels arbitraires doivent faire particulièrement attention et envisager un autre vecteur d'attaque pour ERC777.