La version rapide : La réentrance, c'est comme un hacker qui vous rappelle pendant que vous êtes encore en train de leur transférer de l'argent—ils vident votre portefeuille avant même que la transaction ne soit terminée.
Voici la dure réalité : Plus de $100M a été perdu à cause des exploits de réentrées. Le plus célèbre ? Le hack de la DAO (2016) a volé $50M en ETH en exploitant cette vulnérabilité exacte.
Comment l'attaque fonctionne (En utilisant la logique de code réelle)
Imaginez que le ContratA détient 10 ETH et que le ContratB a un solde de 1 ETH qui y est stocké.
Lorsque ContractB appelle withdrawAll(), voici ce qui devrait se passer :
Vérifiez le solde > 0 ✓
Renvoyer ETH ✓
Mettre à jour le solde à 0 ✓
Mais voici où ça casse : L'attaquant exploite l'ordre des opérations.
Le Flux d'Exploitation :
L'attaquant appelle attack() → ce qui appelle withdrawAll() sur ContractA
ContractA envoie 1 ETH et déclenche la fonction de repli de l'attaquant()
Avant que le solde ne soit mis à jour à 0, fallback() appelle immédiatement withdrawAll() à nouveau.
ContractA vérifie : “Le solde > 0 ?” OUI ( parce qu'il n'a pas encore été mis à jour !)
Envoie un autre 1 ETH → déclenche à nouveau fallback()
Cela boucle jusqu'à ce que le ContratA soit complètement vidé.
Aperçu clé : La mise à jour du solde se produit APRÈS le transfert d'ETH. C'est la fenêtre de vulnérabilité.
Trois stratégies de défense
1. Le Modificateur nonReentrant (Protection de Fonction Unique)
Verrouillez la fonction pendant son exécution. Aucune réentrée autorisée :
solidity
modificateur nonReentrant {
require(!locked, “Pas de réentrance”);
verrouillé = vrai;
_;
verrouillé = faux;
}
Simple, mais ne protège qu'une fonction à la fois.
Vérifications : Vérifier les conditions (balance > 0)
Effets : Mettre à jour l'état (balance = 0) ← Déplacer cela AVANT d'envoyer ETH
Interactions: Envoyer ETH
Commande incorrecte :
require(balance > 0);
→ envoyer ETH
→ solde = 0; // Trop tard !
Ordre correct :
require(balance > 0);
→ solde = 0; // Mettre à jour PREMIER
→ envoyer ETH // Puis interagir
Maintenant, même si fallback() réintègre, le solde est déjà de 0. L'attaque échoue.
3. GlobalReentrancyGuard (Protection entre contrats)
Pour les systèmes complexes avec plusieurs contrats interagissant, utilisez un contrat de garde centralisé qui suit l'état de verrouillage de tous les contrats. Lorsque le ContratA appelle le ContratB, le garde l'enregistre—si le ContratB essaie de rappeler le système avant de retourner, le garde le bloque.
Pourquoi cela importe
La réentrance n'est pas seulement un problème de Solidity—c'est un problème de conception. Chaque fois que vous envoyez de l'ETH ou appelez des fonctions externes, vous transmettez le contrôle à un code non fiable. La fonction de fallback de l'attaquant s'exécute dans le contexte de VOTRE contrat.
Les données : Chainalysis a trouvé qu'environ 60 % des exploits de haute valeur en 2023-2024 impliquaient de la réentrance ou des motifs similaires. Des projets phares comme Yearn, Curve et Balancer ont tous connu des frayeurs de réentrance.
Résultat final : Utilisez Checks-Effects-Interactions par défaut. Ajoutez nonReentrant là où c'est nécessaire. Pour les systèmes multi-contrats, implémentez GlobalReentrancyGuard. Les 100 millions de dollars perdus auraient pu être économisés avec ces modèles de base.
Suivez @TheBlockChainer pour plus d'analyses approfondies sur la sécurité Web3.
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.
Attaque de réentrance : Pourquoi les Smart Contracts continuent d'être vidés ( et comment y mettre fin )
La version rapide : La réentrance, c'est comme un hacker qui vous rappelle pendant que vous êtes encore en train de leur transférer de l'argent—ils vident votre portefeuille avant même que la transaction ne soit terminée.
Voici la dure réalité : Plus de $100M a été perdu à cause des exploits de réentrées. Le plus célèbre ? Le hack de la DAO (2016) a volé $50M en ETH en exploitant cette vulnérabilité exacte.
Comment l'attaque fonctionne (En utilisant la logique de code réelle)
Imaginez que le ContratA détient 10 ETH et que le ContratB a un solde de 1 ETH qui y est stocké.
Lorsque ContractB appelle withdrawAll(), voici ce qui devrait se passer :
Mais voici où ça casse : L'attaquant exploite l'ordre des opérations.
Le Flux d'Exploitation :
Aperçu clé : La mise à jour du solde se produit APRÈS le transfert d'ETH. C'est la fenêtre de vulnérabilité.
Trois stratégies de défense
1. Le Modificateur nonReentrant (Protection de Fonction Unique)
Verrouillez la fonction pendant son exécution. Aucune réentrée autorisée : solidity modificateur nonReentrant { require(!locked, “Pas de réentrance”); verrouillé = vrai; _; verrouillé = faux; }
Simple, mais ne protège qu'une fonction à la fois.
2. Modèle Vérifications-Effects-Interactions (Protection Multi-Fonction )
C'est le facteur décisif :
Commande incorrecte :
require(balance > 0); → envoyer ETH → solde = 0; // Trop tard !
Ordre correct :
require(balance > 0); → solde = 0; // Mettre à jour PREMIER → envoyer ETH // Puis interagir
Maintenant, même si fallback() réintègre, le solde est déjà de 0. L'attaque échoue.
3. GlobalReentrancyGuard (Protection entre contrats)
Pour les systèmes complexes avec plusieurs contrats interagissant, utilisez un contrat de garde centralisé qui suit l'état de verrouillage de tous les contrats. Lorsque le ContratA appelle le ContratB, le garde l'enregistre—si le ContratB essaie de rappeler le système avant de retourner, le garde le bloque.
Pourquoi cela importe
La réentrance n'est pas seulement un problème de Solidity—c'est un problème de conception. Chaque fois que vous envoyez de l'ETH ou appelez des fonctions externes, vous transmettez le contrôle à un code non fiable. La fonction de fallback de l'attaquant s'exécute dans le contexte de VOTRE contrat.
Les données : Chainalysis a trouvé qu'environ 60 % des exploits de haute valeur en 2023-2024 impliquaient de la réentrance ou des motifs similaires. Des projets phares comme Yearn, Curve et Balancer ont tous connu des frayeurs de réentrance.
Résultat final : Utilisez Checks-Effects-Interactions par défaut. Ajoutez nonReentrant là où c'est nécessaire. Pour les systèmes multi-contrats, implémentez GlobalReentrancyGuard. Les 100 millions de dollars perdus auraient pu être économisés avec ces modèles de base.
Suivez @TheBlockChainer pour plus d'analyses approfondies sur la sécurité Web3.