Le 11 octobre 2022, TempleDAO a perdu environ 2,3 millions de dollars (1 831 ETH) lorsqu'un attaquant a exploité un contrôle d'accès manquant dans la fonction migrateStake() du contrat StaxLPStaking. La fonction était censée migrer la position stakée propre d'un utilisateur vers un nouveau contrat — mais elle ne vérifiait pas que l'appelant possédait la position migrée.
Ce qui s'est passé
Le contrat StaxLPStaking de TempleDAO permettait aux utilisateurs de staker des jetons LP. Il incluait une fonction migrateStake(address oldStaking, uint256 amount) destinée aux utilisateurs pour déplacer leur propre stake vers un contrat de staking mis à niveau.
La faille fatale : migrateStake() faisait confiance aux paramètres fournis par l'appelant sans vérifier que l'appelant possédait réellement le stake migré. Elle appelait migrateWithdraw de l'ancien contrat de staking pour une adresse arbitraire, puis créditait le résultat — signifiant que tout appelant pouvait migrer (et donc retirer) la position entière d'un autre staker vers une destination qu'il contrôlait.
L'attaque était en conséquence triviale :
- L'attaquant a appelé
migrateStake()en spécifiant une destination qu'il contrôlait et le contrat de staking TempleDAO détenant tous les stakes utilisateurs. - La fonction, manquant le contrôle de propriété, a migré et libéré les jetons LP stakés à l'attaquant.
- L'attaquant a déballé la position LP et est parti avec ~1 831 ETH (~2,3 M$).
L'exploit entier était une transaction unique exploitant un seul require manquant.
Conséquences
- TempleDAO a mis en pause les contrats affectés et engagé l'attaquant via des messages on-chain.
- L'équipe a publié un post-mortem identifiant la validation de propriété d'appelant manquante comme seule cause racine.
- Les fonds volés ont été blanchis via Tornado Cash ; la récupération a été minimale.
Pourquoi c'est important
TempleDAO est l'un des exemples les plus purs du catalogue de la classe de bug « contrôle d'accès manquant » — distincte de la manipulation d'oracle, de la réentrance ou des exploits économiques. Il n'y avait pas de flash loan astucieux, pas de manipulation de prix, pas de mécanisme nouveau. Il y avait une fonction qui aurait dû vérifier que msg.sender possédait la position et qui ne le faisait pas.
La leçon structurelle est presque embarrassamment simple mais récurrente :
Chaque fonction qui déplace les actifs d'un utilisateur doit vérifier que l'appelant est autorisé à déplacer ces actifs spécifiques. Pas « l'appelant est-il un utilisateur valide » — « l'appelant possède-t-il la position exacte que cet appel affecte ».
Le pattern se répète à travers le catalogue : TempleDAO (migrateStake), Exactly Protocol (marché non validé), Hedgey Finance (claimLockup non vérifié), Seneca (drainage Chamber). Chacun est une fonction qui effectue une opération privilégiée ou déplaçant des fonds sur la base de paramètres fournis par l'appelant, sans valider la relation de l'appelant aux actifs affectés.
Ces bugs sont trivialement attrapés par même un audit superficiel ou par des tests unitaires basiques de contrôle d'accès (« l'adresse B peut-elle migrer le stake de l'adresse A ? »). La fréquence à laquelle ils sont quand même livrés — particulièrement dans les fonctions de migration et de périphérie écrites rapidement et tard — est l'un des thèmes silencieux récurrents du catalogue.
Sources & preuves on-chain
- [01]halborn.comhttps://www.halborn.com/blog/post/explained-the-templedao-hack-october-2022
- [02]bitcoinist.comhttps://bitcoinist.com/temple-dao-exploited-for-2m/
- [03]medium.comhttps://medium.com/neptune-mutual/decoding-stax-finances-vulnerability-4e9a7abac82c