Qui a vraiment appelé : la faille d'authentification tx.origin

Sécurité des Cryptomonnaies & Blockchain Niveau 4/4 ~7 min 23 octobre 2026

Le défi

Le vault on-chain de Pembrook ne laisse retirer des fonds qu'à son propriétaire, et la clé du propriétaire n'a jamais fuité. Pourtant, le vault a été vidé après que le propriétaire a utilisé un nouveau site d'airdrop lui demandant de cliquer sur Claim. La protection de withdraw fait ce que l'auteur a écrit : l'auteur a simplement posé la mauvaise question sur l'identité de l'appelant. Lisez le contrat et nommez l'expression, dans la vérification du propriétaire, qui a permis à un contrat avec lequel le propriétaire n'a fait qu'interagir de dépenser en son nom.

Ce que tu vas apprendre

  • Distinguer msg.sender (appelant immédiat) de tx.origin (signataire de la transaction)
  • Expliquer comment un contrat de phishing maintient tx.origin égal à la victime
  • Identifier tx.origin dans un contrôle d'accès comme la vulnérabilité
  • Le comparer à un contrôle de propriété correct basé sur msg.sender
  • Énoncer la règle : autoriser avec msg.sender, pas avec tx.origin

Compétences testées

Revue de smart contractsSémantique de SolidityAnalyse du contrôle d'accès

Prérequis

  • Lire du Solidity
  • Savoir ce qu'est une chaîne d'appels entre contrats

Comment ça marche

Chaque appel Solidity voit deux identités. msg.sender est celui qui a appelé directement cette fonction, ce qui peut être un autre contrat. tx.origin est le compte externe (EOA) qui a signé toute la transaction, inchangé quel que soit le nombre de contrats traversés par l'appel.

Autoriser sur tx.origin ouvre la porte au phishing. Si le owner est incité à appeler un contrat malveillant, et que ce contrat appelle le vault, alors dans le vault msg.sender est le contrat malveillant mais tx.origin reste le owner. Un contrôle tx.origin == owner passe, et le code de l'attaquant dépense en tant que owner sans jamais toucher à la clé du owner.

La fonction transferOwnership du même contrat montre la forme correcte : elle compare msg.sender, qui ne peut pas être piloté via un intermédiaire.

Erreurs fréquentes

  • Répondre msg.sender. C'est le contrôle sûr, utilisé correctement dans transferOwnership.
  • Accuser une clé divulguée. Aucune clé n'a fuité : le owner a été piégé pour qu'il initie la transaction.
  • Pointer transfer ou le contrôle du solde. Ils sont corrects : la faille se trouve dans la façon d'identifier le owner.
  • Parler de reentrancy. Rien ne ré-entre : l'appel unique passe simplement une protection vulnérable au phishing.

Comment s'en protéger

Identifiez les appelants avec msg.sender.

  • Remplacez tx.origin == owner par msg.sender == owner dans chaque contrôle d'accès.
  • Évitez complètement tx.origin pour l'autorisation. Ses rares usages légitimes sont déconseillés, et l'account abstraction érode encore la notion d'origine unique.
  • Ajoutez des tests qui appellent les fonctions privilégiées via un contrat intermédiaire, afin qu'une protection vulnérable au phishing échoue en CI.

Solution complète

Les membres Pro et Max débloquent la solution complète étape par étape.

Passer Pro

Statistiques de la communauté

192 résolutions
86% taux de réussite
M2F14M3 Premier sang

Hacks du jour associés

38 000+ Hackers Vrais labs Gratuit
Commencer Gratuitement ou résolvez le hack du jour, sans compte