Ces 200 ETH se composaient de quatre lots de 50 ETH que le contrat avait remportés lors d'enchères MakerDAO sans aucune offre, pendant les liquidations du «Black Thursday» de mars 2020, mais qu'il n'avait jamais finalement réclamés.
L'une des fonctions non protégées de l'ancien contrat ne vérifiait pas qui l'appelait. Cela a permis à l'attaquant de donner à un contrat sous son contrôle le contrôle total du compte de ce contrat dans le système MakerDAO. En une seule transaction, l'attaquant a réglé les anciennes enchères et retiré la garantie qui y était détenue.
Transactions clés (heures en UTC)
| Heure | TXID | Description |
|---|---|---|
| 2026-10-06 05:57:23 | 0xd4c0b18a058e7f0a12855f30174f4cb1e973c15c886063deab97e1a21f048ac6 | Retrait de 0.1 ETH depuis Tornado Cash. Il s'agit du seul financement reçu par ce compte. |
| 2026-10-06 06:12:11 | 0x4a587af4213cc345c4c109fbf5fec46f9643183f91a9edf60305380f31ad1167 | Déploiement du contrat d'attaque utilisé pour exploiter la vulnérabilité. |
| 2026-10-06 06:13:11 | 0xbb6940f7c2a1e68cafbae7bb9b94d09af9af06ec3a114f6996f2cab993f3a88c | La transaction d'attaque. Le contrat d'attaque a obtenu des permissions déléguées via la fonction du keeper 0x8804d1de, a réglé les enchères 1457-1460 et a envoyé 200 ETH au compte externe (EOA) de l'attaquant. |
| 2026-10-06 06:19:35 | 0xb8ecff9c129d8d9331c85558eaeddff29a38c4c16b71a40986acbf8f6febefeb | Le premier de neuf dépôts de 10 ETH dans le routeur Tornado Cash. |
Adresses clés
| Adresse | Rôle |
|---|---|
| 0x01EB957E5C7DcDDD60F3C875956cCc6fb9BdA5FA | Le compte externe (EOA) de l'attaquant. |
| 0xEc997d2aD033277913d6002277353368E8321dcF | Le contrat d'attaque. |
| 0xf09a13072Ed939B79Bc25B66AA3a836ea6DCC170 | Le module adaptateur malveillant, qui détient toujours des permissions déléguées sur le compte de la victime dans Vat. |
| 0x9c05a05893Ada984FC20D0DA0c046De5Cc0e8273 | Le contrat vulnérable (ancien keeper d'enchères, AdminUpgradeabilityProxy). |
| 0x68399ed8aa33C5b43F863EE6782de492006A5546 | L'implémentation du contrat vulnérable (code source non vérifié). |
| 0xaDC374E77b89Af0B8B39F7c47E8e0A37B6DaF073 | Le propriétaire et opérateur du keeper en mars 2020. |
| 0xd8a04F5412223F513DC55F839574430f5EC15531 | MakerDAO ETH-A Flipper, un mécanisme d'enchères mis hors service pour la vente de garanties. |
| 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B | MakerDAO Vat, le module comptable central. |
| 0x2F0b23f53734252Bda2277357e97e1517d6B042A | MakerDAO ETH-A GemJoin, le point de sortie de l'actif en garantie. |
| 0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b | Le routeur Tornado Cash, l'adresse ayant reçu les fonds volés. |
| 0x12D66f87A04A9E220743712cE6d9bB1B5616B8Fc | Le pool Tornado Cash de 0.1 ETH, source du financement initial de l'attaquant. |
Comment l'attaque s'est déroulée
Déploiement du module
L'exploit a commencé lorsque le contrat d'attaque a créé un module adaptateur à 0xf09a13072Ed939B79Bc25B66AA3a836ea6DCC170. Lors de sa création, le module a reçu les paramètres suivants: le Flipper, Vat, ETH-A GemJoin, le type de garantie (ilk), WETH, une adresse de paiement et quatre identifiants d'enchères.
Transfert des permissions
Le contrat d'attaque a appelé la fonction keeper 0x8804d1de et lui a transmis l'adaptateur nouvellement créé à 0xf09. Le keeper a ensuite appelé les fonctions drip() et vat() du module, vérifié via Vat.can() si des permissions lui avaient déjà été accordées, puis appelé Vat.hope(). Cela a donné au module des permissions illimitées pour gérer le compte du keeper dans le système Vat.
Le callback
Le keeper a ensuite appelé la fonction join() du contrat d'attaque. Cela a transféré le contrôle au code écrit par l'attaquant, à un moment où les nouvelles permissions étaient déjà en vigueur.
Finalisation des enchères
Dans le callback, le module a appelé la fonction deal(id) du Flipper ETH-A désactivé pour les enchères 1457, 1458, 1459 et 1460. En mars 2020, le keeper avait initialement remporté chacun des quatre lots de 50 ETH avec une offre nulle, mais n'avait jamais finalisé les transactions. Une fois les enchères finalisées, 200 ETH ont été crédités en tant que garantie ETH-A sur le compte du keeper dans Vat.
Retrait des fonds
Le module a lu le solde de garantie du keeper et a utilisé les permissions obtenues pour transférer la totalité des 200 ETH du compte du keeper dans Vat vers sa propre adresse via la fonction flux(). Il a ensuite retiré la garantie via ETH-A GemJoin sous forme de 200 WETH et envoyé les WETH au contrat d'attaque.
Quel est le cœur de la vulnérabilité?
La cause profonde de l'attaque était l'absence de contrôle d'accès sur la fonction 0x8804d1de dans l'implémentation du keeper à 0x68399ed8aa33C5b43F863EE6782de492006A5546.
Toutes les autres fonctions privilégiées du contrat, y compris les wrappers du keeper pour les opérations hope, flux et move, exécutent d'abord une vérification ds-auth et rejettent les appels non autorisés avec l'erreur ds-auth-unauthorized.
La fonction 0x8804d1de, en revanche, accepte n'importe quelle adresse comme adaptateur, appelle Vat.hope() pour cette adresse si le keeper ne lui a pas encore accordé de permissions, puis appelle join() sur la même adresse.
Parce que le keeper a ensuite appelé join(), le module de l'attaquant a pu exécuter son propre code à un moment où ces permissions étaient déjà en vigueur.
Les quatre lots inutilisés de 2020 ont rendu cette vulnérabilité rentable pour l'attaquant. N'importe qui peut appeler la fonction deal pour une enchère.
DeFiTuna a appris à arrondir: une erreur logique a coûté $570 mille en USDC20 juil. 2026En savoir plusMouvement des fonds
L'attaquant a reçu la totalité des 200 ETH directement dans la transaction utilisée pour exploiter la vulnérabilité. À 06:19:35 UTC, seulement six minutes plus tard, l'attaquant a commencé à transférer les fonds vers Tornado Cash, en les envoyant sous forme de 20 dépôts de 10 ETH.

