Sécurité des smart contracts, la faille qui coûte le plus cher
David Touzet11 août 20269 min de lectureLes vols sur blockchain ont dépassé 5 milliards de dollars cette année, et 55 % viennent de défauts dans le code des contrats. Ce ne sont pas des attaques sophistiquées. Voici les 2 fautes qui reviennent le plus, montrées avant et après correction.
Le vol le plus simple du monde
Commençons par un cas réel, parce qu’il n’a rien de spectaculaire et que c’est bien le problème.
Le déroulé tient en 5 mouvements. L’attaquant achète une petite quantité d’un jeton, pour quelques dizaines de centimes. Puis il appelle la fonction qui détruit des jetons, et en détruit près de 10 millions qui ne lui appartiennent pas. L’offre s’effondre, donc les quelques jetons qu’il possède valent soudain beaucoup plus. Il revend. Bilan, environ 316 000 dollars.
Où était la faute. La fonction de destruction était publique. N’importe qui pouvait l’appeler. Il manquait une ligne.
Ce qui rend ce cas instructif. Aucune cryptographie cassée, aucune faille exotique. Juste une porte laissée ouverte, dans un code que tout le monde pouvait lire, puisque c’est le principe même d’un contrat déposé sur une blockchain.
Faute n°1, le contrôle d’accès
C’est la première cause de vol, année après année. Et elle se voit en 2 lignes.
Le code vulnérable.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Jeton {
mapping(address => uint256) public solde;
uint256 public offreTotale;
// ❌ Rien ne limite l'appel. N'importe qui detruit les jetons de n'importe qui.
function bruler(address de, uint256 montant) external {
solde[de] -= montant;
offreTotale -= montant;
}
}
Le code corrigé.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Jeton {
address public proprietaire;
mapping(address => uint256) public solde;
uint256 public offreTotale;
constructor() {
proprietaire = msg.sender;
}
// ✅ Un modificateur applique le controle AVANT le corps de la fonction.
modifier seulementProprietaire() {
require(msg.sender == proprietaire, "Reserve au proprietaire.");
_;
}
function bruler(address de, uint256 montant) external seulementProprietaire {
solde[de] -= montant;
offreTotale -= montant;
}
}
⚠ Le piège qui fait tomber même les équipes sérieuses. Beaucoup importent une bibliothèque de gestion de propriété, se croient protégées, et oublient d’appliquer le modificateur sur la fonction sensible. L’import ne protège de rien. C’est le mot posé sur la ligne de la fonction qui protège.
Le contrôle à faire. Listez toutes les fonctions qui écrivent quelque chose, et pour chacune, répondez à une seule question. Qui a le droit de l’appeler ? S’il n’y a pas de réponse écrite dans le code, la réponse est tout le monde.
Faute n°2, le rappel pendant l’exécution
Celle-ci est plus subtile, et elle a coûté des dizaines de millions.
Le mécanisme. Votre contrat envoie de l’argent à une adresse. Si cette adresse est elle-même un contrat, l’envoi lui donne la main. Elle en profite pour rappeler votre fonction avant que celle-ci ait fini de mettre à jour ses comptes. Et elle recommence, en boucle, tant qu’il reste des fonds.
Le code vulnérable.
function retirer() external {
uint256 montant = solde[msg.sender];
require(montant > 0, "Rien a retirer.");
// ❌ On envoie AVANT de mettre le solde a zero.
// Le destinataire reprend la main ici et rappelle retirer().
(bool ok, ) = msg.sender.call{value: montant}("");
require(ok, "Echec du transfert.");
solde[msg.sender] = 0; // trop tard, la boucle est deja passee
}
Le code corrigé. On inverse simplement l’ordre.
function retirer() external {
uint256 montant = solde[msg.sender];
require(montant > 0, "Rien a retirer.");
// ✅ On ecrit d'abord, on envoie ensuite.
// Au 2e appel, le solde vaut deja zero et le require bloque.
solde[msg.sender] = 0;
(bool ok, ) = msg.sender.call{value: montant}("");
require(ok, "Echec du transfert.");
}
La règle à retenir, et elle tient en 3 mots. Vérifier, écrire, envoyer. Dans cet ordre, toujours. Toute fonction qui envoie de l’argent avant d’avoir mis ses compteurs à jour est exploitable.
Ce que l’IA change dans la relecture
Les outils automatiques existent depuis longtemps. Leur défaut n’est pas de rater des failles, c’est d’en inventer.
Le problème mesuré. Sur un contrat analysé par un outil classique, 24 signalements sont remontés. Un seul était réel. Les 23 autres étaient des fausses alertes, dues au fait que l’équipe avait implémenté son contrôle d’accès autrement que ne l’attendait l’outil.
Pourquoi ça compte plus qu’il n’y paraît. Un auditeur noyé sous 23 fausses alertes finit par les survoler, et c’est le jour où il survole la vingt-quatrième que ça coûte cher.
Ce que l’analyse par IA apporte. Elle comprend le contexte, donc elle sait reconnaître un contrôle d’accès écrit d’une façon inhabituelle. Sur ce même cas, 19 des 23 fausses alertes ont été écartées, soit 82 % de bruit en moins.
⚠ Ce qu’elle n’apporte pas. Elle ne remplace pas la relecture humaine. Un modèle à qui l’on donne 3 000 lignes d’un coup se met à inventer, faute de pouvoir tout tenir en tête. Les approches qui marchent découpent, interrogent fonction par fonction, et confrontent les réponses.
C’est exactement la logique que nous appliquons dans la revue de sécurité automatique, et le harnais que nous posons sur nos agents part du même principe. On borne, puis on vérifie.
Les 4 exigences avant de signer
Que vous fassiez écrire un contrat ou que vous en utilisiez un, voici ce qui se vérifie sans être développeur.
1. Le rapport d’audit complet, pas le résumé. Un résumé ne dit jamais ce qui a été laissé de côté. Demandez la liste des points signalés et, pour chacun, ce qui a été corrigé ou assumé.
2. La preuve que le code déployé est celui qui a été audité. Ça se vérifie publiquement, le code d’un contrat déposé est consultable par tous. Un prestataire qui refuse cette vérification vous dit quelque chose.
3. La procédure du mauvais jour. Qui prévient, qui coupe, sous quel délai. Une équipe qui n’a jamais écrit cette procédure ne l’improvisera pas à 3 heures du matin.
4. Ce qui se passe si personne ne peut arrêter. Certains contrats prévoient une pause d’urgence, d’autres non, et c’est un choix qui se discute avant, pas après.
Le réflexe qui résume tout. Sur une blockchain, il n’existe pas de bouton annuler. La seule protection est ce que vous avez vérifié avant, et ce que vous êtes capable de montrer après. C’est le même principe que la traçabilité que nous imposons à nos équipes d’agents IA.
Nos pages liées
Pour aller plus loin.
Questions fréquentes
Un site sur mesure, piloté par des experts.
À Montpellier, on conçoit, développe et pilote votre présence web. Vous restez concentré sur vos clients, on gère la technique et le contenu.
Faire le point sur votre siteUne équipe IA qui accélère votre visibilité.
SEO, rédaction, réseaux sociaux, publicité et veille. 12 agents IA métier travaillent en continu pour générer du trafic et des leads.
Voir les 12 agents