L'adresse que les signataires n'ont jamais vue : un bundle de wallet piégé
Le défi
Brynmor a validé un virement de routine. Trouve où le code change le destinataire. Donne l'adresse où va vraiment la transaction.
Ce que tu vas apprendre
- Repérer du code injecté qui ne se déclenche que pour certaines adresses de wallet
- Distinguer les adresses des victimes dans une liste de cibles de l'adresse de l'attaquant
- Expliquer ce que l'operation 1 (delegatecall) permet à une transaction Safe
- Comprendre pourquoi l'écran d'un signataire peut différer de ce qui est réellement signé
- Citer des contrôles contre la falsification du front-end et la signature à l'aveugle
Compétences testées
Prérequis
- Lire du JavaScript
- Savoir ce qu'est un wallet multisig
Comment ça marche
Un multisig Safe n'exécute une transaction que lorsque suffisamment d'owners ont signé ses champs : to, value, data et operation. Les owners signent en général via une appli web, donc celui qui contrôle le JavaScript de cette appli contrôle ce qui est réellement signé.
operation vaut 0 pour un appel normal et 1 pour un delegatecall. Un delegatecall exécute le code du contrat cible à l'intérieur du Safe lui-même, avec le solde et le stockage du Safe : un seul delegatecall signé vers un contrat de l'attaquant lui livre donc tout le wallet.
En février 2025, des attaquants ont fait exactement cela à Bybit : du JavaScript injecté dans le front-end de Safe{Wallet} attendait le Safe du cold wallet de la plateforme, remplaçait un transfert de routine par un delegatecall, puis rétablissait l'affichage après la signature. Le contrat de l'attaquant a ensuite siphonné environ 401 000 ETH et d'autres tokens, soit à peu près 1,5 milliard de dollars.
Erreurs fréquentes
- Répondre avec le warm wallet (0x0Ac51AA8300882aAa03F7678770495345Dc51774). C'est ce qu'affichait l'écran de relecture et ce que les signataires croyaient approuver. Le bundle écrase
toavant la signature et le restaure après. - Répondre avec une adresse de
waouba. Ces listes sont les cibles : le Safe et les signataires de Brynmor, comme le montre queued-tx.json. Elles décident quand le piège se déclenche, pas où va l'argent. - Faire confiance aux calldata décodées.
0xa9059cbbest le sélecteur detransfer(address,uint256), donc un wallet affiche un transfert de valeur nulle. Avec l'operation 1, c'est le contrat de l'attaquant qui décide de ce que cet appel fait vraiment.
Comment s'en protéger
- Vérifie chaque transaction multisig sur un appareil indépendant : clear signing sur hardware wallet de
to,operationetdatadécodé, ou unsafeTxHashrecalculé avec un outil hors ligne, jamais seulement la page web. - Traite
operation: 1comme critique : un Safe Guard peut rejeter les delegatecall sauf vers des bibliothèques autorisées comme MultiSend. - Fige le front-end du wallet sur une version relue (auto-hébergée ou adressée par contenu), surveille le hash du bundle servi et restreins qui peut écrire dans le bucket d'hébergement.
- Réserve la signature du cold wallet à des machines dédiées et suis une checklist écrite pour les gros mouvements.